diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index c1a1d5d7db..5be607567f 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -43,7 +43,7 @@ jobs: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} build: - name: build-${{ matrix.os }} + name: build-${{ matrix.os }}-${{ matrix.ghc }} if: always() needs: prepare-release runs-on: ${{ matrix.os }} @@ -52,18 +52,25 @@ jobs: matrix: include: - os: ubuntu-20.04 + ghc: "8.10.7" + cache_path: ~/.cabal/store + - os: ubuntu-20.04 + ghc: "9.6.3" cache_path: ~/.cabal/store asset_name: simplex-chat-ubuntu-20_04-x86-64 desktop_asset_name: simplex-desktop-ubuntu-20_04-x86_64.deb - os: ubuntu-22.04 + ghc: "9.6.3" cache_path: ~/.cabal/store asset_name: simplex-chat-ubuntu-22_04-x86-64 desktop_asset_name: simplex-desktop-ubuntu-22_04-x86_64.deb - os: macos-latest + ghc: "9.6.3" cache_path: ~/.cabal/store asset_name: simplex-chat-macos-x86-64 desktop_asset_name: simplex-desktop-macos-x86_64.dmg - os: windows-latest + ghc: "9.6.3" cache_path: C:/cabal asset_name: simplex-chat-windows-x86-64 desktop_asset_name: simplex-desktop-windows-x86_64.msi @@ -82,16 +89,17 @@ jobs: - name: Setup Haskell uses: haskell/actions/setup@v2 with: - ghc-version: "8.10.7" - cabal-version: "latest" + ghc-version: ${{ matrix.ghc }} + cabal-version: "3.10.1.0" - - name: Cache dependencies - uses: actions/cache@v3 + - name: Restore cached build + id: restore_cache + uses: actions/cache/restore@v3 with: path: | ${{ matrix.cache_path }} dist-newstyle - key: ${{ matrix.os }}-${{ hashFiles('cabal.project', 'simplex-chat.cabal') }} + key: ${{ matrix.os }}-ghc${{ matrix.ghc }}-${{ hashFiles('cabal.project', 'simplex-chat.cabal') }} # / Unix @@ -106,7 +114,7 @@ jobs: echo " flags: +openssl" >> cabal.project.local - name: Install AppImage dependencies - if: startsWith(github.ref, 'refs/tags/v') && matrix.os == 'ubuntu-20.04' + if: startsWith(github.ref, 'refs/tags/v') && matrix.asset_name && matrix.os == 'ubuntu-20.04' run: sudo apt install -y desktop-file-utils - name: Install pkg-config for Mac @@ -132,7 +140,7 @@ jobs: echo "bin_hash=$(echo SHA2-512\(${{ matrix.asset_name }}\)= $(openssl sha512 $path | cut -d' ' -f 2))" >> $GITHUB_OUTPUT - name: Unix upload CLI binary to release - if: startsWith(github.ref, 'refs/tags/v') && matrix.os != 'windows-latest' + if: startsWith(github.ref, 'refs/tags/v') && matrix.asset_name && matrix.os != 'windows-latest' uses: svenstaro/upload-release-action@v2 with: repo_token: ${{ secrets.GITHUB_TOKEN }} @@ -141,7 +149,7 @@ jobs: tag: ${{ github.ref }} - name: Unix update CLI binary hash - if: startsWith(github.ref, 'refs/tags/v') && matrix.os != 'windows-latest' + if: startsWith(github.ref, 'refs/tags/v') && matrix.asset_name && matrix.os != 'windows-latest' uses: softprops/action-gh-release@v1 env: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} @@ -151,7 +159,7 @@ jobs: ${{ steps.unix_cli_build.outputs.bin_hash }} - name: Setup Java - if: startsWith(github.ref, 'refs/tags/v') + if: startsWith(github.ref, 'refs/tags/v') && matrix.asset_name uses: actions/setup-java@v3 with: distribution: 'corretto' @@ -160,7 +168,7 @@ jobs: - name: Linux build desktop id: linux_desktop_build - if: startsWith(github.ref, 'refs/tags/v') && (matrix.os == 'ubuntu-20.04' || matrix.os == 'ubuntu-22.04') + if: startsWith(github.ref, 'refs/tags/v') && matrix.asset_name && (matrix.os == 'ubuntu-20.04' || matrix.os == 'ubuntu-22.04') shell: bash run: | scripts/desktop/build-lib-linux.sh @@ -169,10 +177,10 @@ jobs: path=$(echo $PWD/release/main/deb/simplex_*_amd64.deb) echo "package_path=$path" >> $GITHUB_OUTPUT echo "package_hash=$(echo SHA2-512\(${{ matrix.desktop_asset_name }}\)= $(openssl sha512 $path | cut -d' ' -f 2))" >> $GITHUB_OUTPUT - + - name: Linux make AppImage id: linux_appimage_build - if: startsWith(github.ref, 'refs/tags/v') && matrix.os == 'ubuntu-20.04' + if: startsWith(github.ref, 'refs/tags/v') && matrix.asset_name && matrix.os == 'ubuntu-20.04' shell: bash run: | scripts/desktop/make-appimage-linux.sh @@ -195,7 +203,7 @@ jobs: echo "package_hash=$(echo SHA2-512\(${{ matrix.desktop_asset_name }}\)= $(openssl sha512 $path | cut -d' ' -f 2))" >> $GITHUB_OUTPUT - name: Linux upload desktop package to release - if: startsWith(github.ref, 'refs/tags/v') && (matrix.os == 'ubuntu-20.04' || matrix.os == 'ubuntu-22.04') + if: startsWith(github.ref, 'refs/tags/v') && matrix.asset_name && (matrix.os == 'ubuntu-20.04' || matrix.os == 'ubuntu-22.04') uses: svenstaro/upload-release-action@v2 with: repo_token: ${{ secrets.GITHUB_TOKEN }} @@ -204,7 +212,7 @@ jobs: tag: ${{ github.ref }} - name: Linux update desktop package hash - if: startsWith(github.ref, 'refs/tags/v') && (matrix.os == 'ubuntu-20.04' || matrix.os == 'ubuntu-22.04') + if: startsWith(github.ref, 'refs/tags/v') && matrix.asset_name && (matrix.os == 'ubuntu-20.04' || matrix.os == 'ubuntu-22.04') uses: softprops/action-gh-release@v1 env: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} @@ -214,7 +222,7 @@ jobs: ${{ steps.linux_desktop_build.outputs.package_hash }} - name: Linux upload AppImage to release - if: startsWith(github.ref, 'refs/tags/v') && matrix.os == 'ubuntu-20.04' + if: startsWith(github.ref, 'refs/tags/v') && matrix.asset_name && matrix.os == 'ubuntu-20.04' uses: svenstaro/upload-release-action@v2 with: repo_token: ${{ secrets.GITHUB_TOKEN }} @@ -223,7 +231,7 @@ jobs: tag: ${{ github.ref }} - name: Linux update AppImage hash - if: startsWith(github.ref, 'refs/tags/v') && matrix.os == 'ubuntu-20.04' + if: startsWith(github.ref, 'refs/tags/v') && matrix.asset_name && matrix.os == 'ubuntu-20.04' uses: softprops/action-gh-release@v1 env: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} @@ -251,6 +259,15 @@ jobs: body: | ${{ steps.mac_desktop_build.outputs.package_hash }} + - name: Cache unix build + uses: actions/cache/save@v3 + if: matrix.os != 'windows-latest' + with: + path: | + ${{ matrix.cache_path }} + dist-newstyle + key: ${{ steps.restore_cache.outputs.cache-primary-key }} + - name: Unix test if: matrix.os != 'windows-latest' timeout-minutes: 30 @@ -284,7 +301,7 @@ jobs: if: matrix.os == 'windows-latest' shell: msys2 {0} run: | - export PATH=$PATH:/c/ghcup/bin + export PATH=$PATH:/c/ghcup/bin:$(echo /c/tools/ghc-*/bin || echo) scripts/desktop/prepare-openssl-windows.sh openssl_windows_style_path=$(echo `pwd`/dist-newstyle/openssl-1.1.1w | sed 's#/\([a-zA-Z]\)#\1:#' | sed 's#/#\\#g') rm cabal.project.local 2>/dev/null || true @@ -326,14 +343,14 @@ jobs: if: startsWith(github.ref, 'refs/tags/v') && matrix.os == 'windows-latest' shell: msys2 {0} run: | - export PATH=$PATH:/c/ghcup/bin + export PATH=$PATH:/c/ghcup/bin:$(echo /c/tools/ghc-*/bin || echo) scripts/desktop/build-lib-windows.sh cd apps/multiplatform ./gradlew packageMsi path=$(echo $PWD/release/main/msi/*imple*.msi | sed 's#/\([a-z]\)#\1:#' | sed 's#/#\\#g') echo "package_path=$path" >> $GITHUB_OUTPUT echo "package_hash=$(echo SHA2-512\(${{ matrix.desktop_asset_name }}\)= $(openssl sha512 $path | cut -d' ' -f 2))" >> $GITHUB_OUTPUT - + - name: Windows upload desktop package to release if: startsWith(github.ref, 'refs/tags/v') && matrix.os == 'windows-latest' uses: svenstaro/upload-release-action@v2 @@ -353,4 +370,13 @@ jobs: body: | ${{ steps.windows_desktop_build.outputs.package_hash }} + - name: Cache windows build + uses: actions/cache/save@v3 + if: matrix.os == 'windows-latest' + with: + path: | + ${{ matrix.cache_path }} + dist-newstyle + key: ${{ steps.restore_cache.outputs.cache-primary-key }} + # Windows / diff --git a/README.md b/README.md index 254a66c2bc..f6630ebbfd 100644 --- a/README.md +++ b/README.md @@ -72,7 +72,7 @@ You must: Messages not following these rules will be deleted, the right to send messages may be revoked, and the access to the new members to the group may be temporarily restricted, to prevent re-joining under a different name - our imperfect group moderation does not have a better solution at the moment. -You can join an English-speaking users group if you want to ask any questions: [#SimpleX-Group-4](https://simplex.chat/contact#/?v=1-2&smp=smp%3A%2F%2Fu2dS9sG8nMNURyZwqASV4yROM28Er0luVTx5X1CsMrU%3D%40smp4.simplex.im%2Fw2GlucRXtRVgYnbt_9ZP-kmt76DekxxS%23%2F%3Fv%3D1-2%26dh%3DMCowBQYDK2VuAyEA0tJhTyMGUxznwmjb7aT24P1I1Wry_iURTuhOFlMb1Eo%253D%26srv%3Do5vmywmrnaxalvz6wi3zicyftgio6psuvyniis6gco6bp6ekl4cqj4id.onion&data=%7B%22type%22%3A%22group%22%2C%22groupLinkId%22%3A%22WoPxjFqGEDlVazECOSi2dg%3D%3D%22%7D) +You can join an English-speaking users group if you want to ask any questions: [#SimpleX users group](https://simplex.chat/contact#/?v=1-4&smp=smp%3A%2F%2FPQUV2eL0t7OStZOoAsPEV2QYWt4-xilbakvGUGOItUo%3D%40smp6.simplex.im%2Fos8FftfoV8zjb2T89fUEjJtF7y64p5av%23%2F%3Fv%3D1-2%26dh%3DMCowBQYDK2VuAyEAQqMgh0fw2lPhjn3PDIEfAKA_E0-gf8Hr8zzhYnDivRs%253D%26srv%3Dbylepyau3ty4czmn77q4fglvperknl4bi2eb2fdy2bh4jxtf32kf73yd.onion&data=%7B%22type%22%3A%22group%22%2C%22groupLinkId%22%3A%22lBPiveK2mjfUH43SN77R0w%3D%3D%22%7D) There is also a group [#simplex-devs](https://simplex.chat/contact#/?v=1-2&smp=smp%3A%2F%2Fu2dS9sG8nMNURyZwqASV4yROM28Er0luVTx5X1CsMrU%3D%40smp4.simplex.im%2F6eHqy7uAbZPOcA6qBtrQgQquVlt4Ll91%23%2F%3Fv%3D1-2%26dh%3DMCowBQYDK2VuAyEAqV_pg3FF00L98aCXp4D3bOs4Sxv_UmSd-gb0juVoQVs%253D%26srv%3Do5vmywmrnaxalvz6wi3zicyftgio6psuvyniis6gco6bp6ekl4cqj4id.onion&data=%7B%22type%22%3A%22group%22%2C%22groupLinkId%22%3A%22XonlixcHBIb2ijCehbZoiw%3D%3D%22%7D) for developers who build on SimpleX platform: @@ -127,6 +127,7 @@ Join our translators to help SimpleX grow! |🇫🇮 fi|Suomi | |[![android app](https://hosted.weblate.org/widgets/simplex-chat/fi/android/svg-badge.svg)](https://hosted.weblate.org/projects/simplex-chat/android/fi/)
[![ios app](https://hosted.weblate.org/widgets/simplex-chat/fi/ios/svg-badge.svg)](https://hosted.weblate.org/projects/simplex-chat/ios/fi/)|[![website](https://hosted.weblate.org/widgets/simplex-chat/fi/website/svg-badge.svg)](https://hosted.weblate.org/projects/simplex-chat/website/fi/)|| |🇫🇷 fr|Français |[ishi_sama](https://github.com/ishi-sama)|[![android app](https://hosted.weblate.org/widgets/simplex-chat/fr/android/svg-badge.svg)](https://hosted.weblate.org/projects/simplex-chat/android/fr/)
[![ios app](https://hosted.weblate.org/widgets/simplex-chat/fr/ios/svg-badge.svg)](https://hosted.weblate.org/projects/simplex-chat/ios/fr/)|[![website](https://hosted.weblate.org/widgets/simplex-chat/fr/website/svg-badge.svg)](https://hosted.weblate.org/projects/simplex-chat/website/fr/)|[✓](https://github.com/simplex-chat/simplex-chat/tree/master/docs/lang/fr)| |🇮🇱 he|עִברִית | |[![android app](https://hosted.weblate.org/widgets/simplex-chat/he/android/svg-badge.svg)](https://hosted.weblate.org/projects/simplex-chat/android/he/)
-||| +|🇭🇺 hu|Magyar | |[![android app](https://hosted.weblate.org/widgets/simplex-chat/hu/android/svg-badge.svg)](https://hosted.weblate.org/projects/simplex-chat/android/hu/)
-||| |🇮🇹 it|Italiano |[unbranched](https://github.com/unbranched)|[![android app](https://hosted.weblate.org/widgets/simplex-chat/it/android/svg-badge.svg)](https://hosted.weblate.org/projects/simplex-chat/android/it/)
[![ios app](https://hosted.weblate.org/widgets/simplex-chat/it/ios/svg-badge.svg)](https://hosted.weblate.org/projects/simplex-chat/ios/it/)|[![website](https://hosted.weblate.org/widgets/simplex-chat/it/website/svg-badge.svg)](https://hosted.weblate.org/projects/simplex-chat/website/it/)|| |🇯🇵 ja|日本語 | |[![android app](https://hosted.weblate.org/widgets/simplex-chat/ja/android/svg-badge.svg)](https://hosted.weblate.org/projects/simplex-chat/android/ja/)
[![ios app](https://hosted.weblate.org/widgets/simplex-chat/ja/ios/svg-badge.svg)](https://hosted.weblate.org/projects/simplex-chat/ios/ja/)|[![website](https://hosted.weblate.org/widgets/simplex-chat/ja/website/svg-badge.svg)](https://hosted.weblate.org/projects/simplex-chat/website/ja/)|| |🇳🇱 nl|Nederlands|[mika-nl](https://github.com/mika-nl)|[![android app](https://hosted.weblate.org/widgets/simplex-chat/nl/android/svg-badge.svg)](https://hosted.weblate.org/projects/simplex-chat/android/nl/)
[![ios app](https://hosted.weblate.org/widgets/simplex-chat/nl/ios/svg-badge.svg)](https://hosted.weblate.org/projects/simplex-chat/ios/nl/)|[![website](https://hosted.weblate.org/widgets/simplex-chat/nl/website/svg-badge.svg)](https://hosted.weblate.org/projects/simplex-chat/website/nl/)|| @@ -134,6 +135,7 @@ Join our translators to help SimpleX grow! |🇧🇷 pt-BR|Português||[![android app](https://hosted.weblate.org/widgets/simplex-chat/pt_BR/android/svg-badge.svg)](https://hosted.weblate.org/projects/simplex-chat/android/pt_BR/)
-|[![website](https://hosted.weblate.org/widgets/simplex-chat/pt_BR/website/svg-badge.svg)](https://hosted.weblate.org/projects/simplex-chat/website/pt_BR/)|| |🇷🇺 ru|Русский ||[![android app](https://hosted.weblate.org/widgets/simplex-chat/ru/android/svg-badge.svg)](https://hosted.weblate.org/projects/simplex-chat/android/ru/)
[![ios app](https://hosted.weblate.org/widgets/simplex-chat/ru/ios/svg-badge.svg)](https://hosted.weblate.org/projects/simplex-chat/ios/ru/)||| |🇹🇭 th|ภาษาไทย |[titapa-punpun](https://github.com/titapa-punpun)|[![android app](https://hosted.weblate.org/widgets/simplex-chat/th/android/svg-badge.svg)](https://hosted.weblate.org/projects/simplex-chat/android/th/)
[![ios app](https://hosted.weblate.org/widgets/simplex-chat/th/ios/svg-badge.svg)](https://hosted.weblate.org/projects/simplex-chat/ios/th/)||| +|🇹🇷 tr|Türkçe | |[![android app](https://hosted.weblate.org/widgets/simplex-chat/tr/android/svg-badge.svg)](https://hosted.weblate.org/projects/simplex-chat/android/tr/)
[![ios app](https://hosted.weblate.org/widgets/simplex-chat/tr/ios/svg-badge.svg)](https://hosted.weblate.org/projects/simplex-chat/ios/tr/)||| |🇺🇦 uk|Українська| |[![android app](https://hosted.weblate.org/widgets/simplex-chat/uk/android/svg-badge.svg)](https://hosted.weblate.org/projects/simplex-chat/android/uk/)
[![ios app](https://hosted.weblate.org/widgets/simplex-chat/uk/ios/svg-badge.svg)](https://hosted.weblate.org/projects/simplex-chat/ios/uk/)|[![website](https://hosted.weblate.org/widgets/simplex-chat/uk/website/svg-badge.svg)](https://hosted.weblate.org/projects/simplex-chat/website/uk/)|| |🇨🇳 zh-CHS|简体中文|[sith-on-mars](https://github.com/sith-on-mars)

[Float-hu](https://github.com/Float-hu)|[![android app](https://hosted.weblate.org/widgets/simplex-chat/zh_Hans/android/svg-badge.svg)](https://hosted.weblate.org/projects/simplex-chat/android/zh_Hans/)
[![ios app](https://hosted.weblate.org/widgets/simplex-chat/zh_Hans/ios/svg-badge.svg)](https://hosted.weblate.org/projects/simplex-chat/ios/zh_Hans/)
 |

[![website](https://hosted.weblate.org/widgets/simplex-chat/zh_Hans/website/svg-badge.svg)](https://hosted.weblate.org/projects/simplex-chat/website/zh_Hans/)|| @@ -232,6 +234,8 @@ You can use SimpleX with your own servers and still communicate with people usin Recent and important updates: +[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) + [Nov 25, 2023. SimpleX Chat v5.4 released: link mobile and desktop apps via quantum resistant protocol, and much better groups](./blog/20231125-simplex-chat-v5-4-link-mobile-desktop-quantum-resistant-better-groups.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). @@ -297,7 +301,7 @@ What is already implemented: 11. Transport isolation - different TCP connections and Tor circuits are used for traffic of different user profiles, optionally - for different contacts and group member connections. 12. Manual messaging queue rotations to move conversation to another SMP relay. 13. Sending end-to-end encrypted files using [XFTP protocol](https://simplex.chat/blog/20230301-simplex-file-transfer-protocol.html). -14. Local files encryption, except videos (to be added later). +14. Local files encryption. We plan to add: @@ -369,12 +373,13 @@ Please also join [#simplex-devs](https://simplex.chat/contact#/?v=1-2&smp=smp%3A - ✅ Desktop client. - ✅ Encryption of local files stored in the app. - ✅ Using mobile profiles from the desktop app. +- ✅ Private notes. +- ✅ Improve sending videos (including encryption of locally stored videos). - 🏗 Improve experience for the new users. - 🏗 Post-quantum resistant key exchange in double ratchet protocol. - 🏗 Large groups, communities and public channels. -- Message delivery relay for senders (to conceal IP address from the recipients' servers and to reduce the traffic). +- 🏗 Message delivery relay for senders (to conceal IP address from the recipients' servers and to reduce the traffic). - Privacy & security slider - a simple way to set all settings at once. -- Improve sending videos (including encryption of locally stored videos). - SMP queue redundancy and rotation (manual is supported). - Include optional message into connection request sent via contact address. - Improved navigation and search in the conversation (expand and scroll to quoted message, scroll to search results, etc.). diff --git a/apps/ios/Shared/AppDelegate.swift b/apps/ios/Shared/AppDelegate.swift index 145e362797..24c0eeb605 100644 --- a/apps/ios/Shared/AppDelegate.swift +++ b/apps/ios/Shared/AppDelegate.swift @@ -15,6 +15,7 @@ class AppDelegate: NSObject, UIApplicationDelegate { logger.debug("AppDelegate: didFinishLaunchingWithOptions") application.registerForRemoteNotifications() if #available(iOS 17.0, *) { trackKeyboard() } + NotificationCenter.default.addObserver(self, selector: #selector(pasteboardChanged), name: UIPasteboard.changedNotification, object: nil) return true } @@ -36,6 +37,10 @@ class AppDelegate: NSObject, UIApplicationDelegate { ChatModel.shared.keyboardHeight = 0 } + @objc func pasteboardChanged() { + ChatModel.shared.pasteboardHasStrings = UIPasteboard.general.hasStrings + } + func application(_ application: UIApplication, didRegisterForRemoteNotificationsWithDeviceToken deviceToken: Data) { let token = deviceToken.map { String(format: "%02hhx", $0) }.joined() logger.debug("AppDelegate: didRegisterForRemoteNotificationsWithDeviceToken \(token)") diff --git a/apps/ios/Shared/ContentView.swift b/apps/ios/Shared/ContentView.swift index d7b9fef218..45e0332dab 100644 --- a/apps/ios/Shared/ContentView.swift +++ b/apps/ios/Shared/ContentView.swift @@ -31,6 +31,7 @@ struct ContentView: View { @State private var showWhatsNew = false @State private var showChooseLAMode = false @State private var showSetPasscode = false + @State private var waitingForOrPassedAuth = true @State private var chatListActionSheet: ChatListActionSheet? = nil private enum ChatListActionSheet: Identifiable { @@ -61,6 +62,10 @@ struct ContentView: View { } if !showSettings, let la = chatModel.laRequest { LocalAuthView(authRequest: la) + .onDisappear { + // this flag is separate from accessAuthenticated to show initializationView while we wait for authentication + waitingForOrPassedAuth = accessAuthenticated + } } else if showSetPasscode { SetAppPasscodeView { chatModel.contentViewAccessAuthenticated = true @@ -73,8 +78,7 @@ struct ContentView: View { showSetPasscode = false alertManager.showAlert(laPasscodeNotSetAlert()) } - } - if chatModel.chatDbStatus == nil { + } else if chatModel.chatDbStatus == nil && AppChatState.shared.value != .stopped && waitingForOrPassedAuth { initializationView() } } @@ -182,7 +186,7 @@ struct ContentView: View { .onAppear { requestNtfAuthorization() // Local Authentication notice is to be shown on next start after onboarding is complete - if (!prefLANoticeShown && prefShowLANotice && !chatModel.chats.isEmpty) { + if (!prefLANoticeShown && prefShowLANotice && chatModel.chats.count > 2) { prefLANoticeShown = true alertManager.showAlert(laNoticeAlert()) } else if !chatModel.showCallView && CallController.shared.activeCallInvitation == nil { diff --git a/apps/ios/Shared/Model/ChatModel.swift b/apps/ios/Shared/Model/ChatModel.swift index 0cc281fda9..c31ad579ab 100644 --- a/apps/ios/Shared/Model/ChatModel.swift +++ b/apps/ios/Shared/Model/ChatModel.swift @@ -54,11 +54,13 @@ final class ChatModel: ObservableObject { @Published var chatDbChanged = false @Published var chatDbEncrypted: Bool? @Published var chatDbStatus: DBMigrationResult? + @Published var ctrlInitInProgress: Bool = false // local authentication @Published var contentViewAccessAuthenticated: Bool = false @Published var laRequest: LocalAuthRequest? // list of chat "previews" @Published var chats: [Chat] = [] + @Published var deletedChats: Set = [] // map of connections network statuses, key is agent connection id @Published var networkStatuses: Dictionary = [:] // current chat @@ -89,14 +91,15 @@ final class ChatModel: ObservableObject { @Published var showCallView = false // remote desktop @Published var remoteCtrlSession: RemoteCtrlSession? - // currently showing QR code - @Published var connReqInv: String? + // currently showing invitation + @Published var showingInvitation: ShowingInvitation? // audio recording and playback @Published var stopPreviousRecPlay: URL? = nil // coordinates currently playing source @Published var draft: ComposeState? @Published var draftChatId: String? // tracks keyboard height via subscription in AppDelegate @Published var keyboardHeight: CGFloat = 0 + @Published var pasteboardHasStrings: Bool = UIPasteboard.general.hasStrings var messageDelivery: Dictionary Void> = [:] @@ -136,7 +139,7 @@ final class ChatModel: ObservableObject { } func removeUser(_ user: User) { - if let i = getUserIndex(user), users[i].user.userId != currentUser?.userId { + if let i = getUserIndex(user) { users.remove(at: i) } } @@ -620,14 +623,16 @@ final class ChatModel: ObservableObject { } func dismissConnReqView(_ id: String) { - if let connReqInv = connReqInv, - let c = getChat(id), - case let .contactConnection(contactConnection) = c.chatInfo, - connReqInv == contactConnection.connReqInv { + if id == showingInvitation?.connId { + markShowingInvitationUsed() dismissAllSheets() } } + func markShowingInvitationUsed() { + showingInvitation?.connChatUsed = true + } + func removeChat(_ id: String) { withAnimation { chats.removeAll(where: { $0.id == id }) @@ -704,6 +709,11 @@ final class ChatModel: ObservableObject { } } +struct ShowingInvitation { + var connId: String + var connChatUsed: Bool +} + struct NTFContactRequest { var incognito: Bool var chatId: String @@ -746,6 +756,8 @@ final class Chat: ObservableObject, Identifiable { case let .group(groupInfo): let m = groupInfo.membership return m.memberActive && m.memberRole >= .member + case .local: + return true default: return false } } diff --git a/apps/ios/Shared/Model/ImageUtils.swift b/apps/ios/Shared/Model/ImageUtils.swift index 41d741e7e6..6437597b19 100644 --- a/apps/ios/Shared/Model/ImageUtils.swift +++ b/apps/ios/Shared/Model/ImageUtils.swift @@ -158,7 +158,8 @@ func imageHasAlpha(_ img: UIImage) -> Bool { return false } -func saveFileFromURL(_ url: URL, encrypted: Bool) -> CryptoFile? { +func saveFileFromURL(_ url: URL) -> CryptoFile? { + let encrypted = privacyEncryptLocalFilesGroupDefault.get() let savedFile: CryptoFile? if url.startAccessingSecurityScopedResource() { do { @@ -185,10 +186,19 @@ func saveFileFromURL(_ url: URL, encrypted: Bool) -> CryptoFile? { func moveTempFileFromURL(_ url: URL) -> CryptoFile? { do { + let encrypted = privacyEncryptLocalFilesGroupDefault.get() let fileName = uniqueCombine(url.lastPathComponent) - try FileManager.default.moveItem(at: url, to: getAppFilePath(fileName)) + let savedFile: CryptoFile? + if encrypted { + let cfArgs = try encryptCryptoFile(fromPath: url.path, toPath: getAppFilePath(fileName).path) + try FileManager.default.removeItem(atPath: url.path) + savedFile = CryptoFile(filePath: fileName, cryptoArgs: cfArgs) + } else { + try FileManager.default.moveItem(at: url, to: getAppFilePath(fileName)) + savedFile = CryptoFile.plain(fileName) + } ChatModel.shared.filesToDelete.remove(url) - return CryptoFile.plain(fileName) + return savedFile } catch { logger.error("ImageUtils.moveTempFileFromURL error: \(error.localizedDescription)") return nil diff --git a/apps/ios/Shared/Model/SimpleXAPI.swift b/apps/ios/Shared/Model/SimpleXAPI.swift index 6a5de6b25b..24a77cb3d3 100644 --- a/apps/ios/Shared/Model/SimpleXAPI.swift +++ b/apps/ios/Shared/Model/SimpleXAPI.swift @@ -365,6 +365,13 @@ func apiSendMessage(type: ChatType, id: Int64, file: CryptoFile?, quotedItemId: } } +func apiCreateChatItem(noteFolderId: Int64, file: CryptoFile?, msg: MsgContent) async -> ChatItem? { + let r = await chatSendCmd(.apiCreateChatItem(noteFolderId: noteFolderId, file: file, msg: msg)) + if case let .newChatItem(_, aChatItem) = r { return aChatItem.chatItem } + createChatItemErrorAlert(r) + return nil +} + private func sendMessageErrorAlert(_ r: ChatResponse) { logger.error("apiSendMessage error: \(String(describing: r))") AlertManager.shared.showAlertMsg( @@ -373,6 +380,14 @@ private func sendMessageErrorAlert(_ r: ChatResponse) { ) } +private func createChatItemErrorAlert(_ r: ChatResponse) { + logger.error("apiCreateChatItem error: \(String(describing: r))") + AlertManager.shared.showAlertMsg( + title: "Error creating message", + message: "Error: \(String(describing: r))" + ) +} + func apiUpdateChatItem(type: ChatType, id: Int64, itemId: Int64, msg: MsgContent, live: Bool = false) async throws -> ChatItem { let r = await chatSendCmd(.apiUpdateChatItem(type: type, id: id, itemId: itemId, msg: msg, live: live), bgDelay: msgDelay) if case let .chatItemUpdated(_, aChatItem) = r { return aChatItem.chatItem } @@ -581,15 +596,15 @@ func apiVerifyGroupMember(_ groupId: Int64, _ groupMemberId: Int64, connectionCo return nil } -func apiAddContact(incognito: Bool) async -> (String, PendingContactConnection)? { +func apiAddContact(incognito: Bool) async -> ((String, PendingContactConnection)?, Alert?) { guard let userId = ChatModel.shared.currentUser?.userId else { logger.error("apiAddContact: no current user") - return nil + return (nil, nil) } let r = await chatSendCmd(.apiAddContact(userId: userId, incognito: incognito), bgTask: false) - if case let .invitation(_, connReqInvitation, connection) = r { return (connReqInvitation, connection) } - AlertManager.shared.showAlert(connectionErrorAlert(r)) - return nil + if case let .invitation(_, connReqInvitation, connection) = r { return ((connReqInvitation, connection), nil) } + let alert = connectionErrorAlert(r) + return (nil, alert) } func apiSetConnectionIncognito(connId: Int64, incognito: Bool) async throws -> PendingContactConnection? { @@ -691,6 +706,9 @@ func apiConnectContactViaAddress(incognito: Bool, contactId: Int64) async -> (Co } func apiDeleteChat(type: ChatType, id: Int64, notify: Bool? = nil) async throws { + let chatId = type.rawValue + id.description + DispatchQueue.main.async { ChatModel.shared.deletedChats.insert(chatId) } + defer { DispatchQueue.main.async { ChatModel.shared.deletedChats.remove(chatId) } } let r = await chatSendCmd(.apiDeleteChat(type: type, id: id, notify: notify), bgTask: false) if case .direct = type, case .contactDeleted = r { return } if case .contactConnection = type, case .contactConnectionDeleted = r { return } @@ -852,8 +870,8 @@ func apiChatUnread(type: ChatType, id: Int64, unreadChat: Bool) async throws { try await sendCommandOkResp(.apiChatUnread(type: type, id: id, unreadChat: unreadChat)) } -func receiveFile(user: any UserLike, fileId: Int64, encrypted: Bool, auto: Bool = false) async { - if let chatItem = await apiReceiveFile(fileId: fileId, encrypted: encrypted, auto: auto) { +func receiveFile(user: any UserLike, fileId: Int64, auto: Bool = false) async { + if let chatItem = await apiReceiveFile(fileId: fileId, encrypted: privacyEncryptLocalFilesGroupDefault.get(), auto: auto) { await chatItemSimpleUpdate(user, chatItem) } } @@ -1123,6 +1141,12 @@ func apiMemberRole(_ groupId: Int64, _ memberId: Int64, _ memberRole: GroupMembe throw r } +func apiBlockMemberForAll(_ groupId: Int64, _ memberId: Int64, _ blocked: Bool) async throws -> GroupMember { + let r = await chatSendCmd(.apiBlockMemberForAll(groupId: groupId, memberId: memberId, blocked: blocked), bgTask: false) + if case let .memberBlockedForAllUser(_, _, member, _) = r { return member } + throw r +} + func leaveGroup(_ groupId: Int64) async { do { let groupInfo = try await apiLeaveGroup(groupId) @@ -1212,9 +1236,11 @@ private func currentUserId(_ funcName: String) throws -> Int64 { throw RuntimeError("\(funcName): no current user") } -func initializeChat(start: Bool, dbKey: String? = nil, refreshInvitations: Bool = true, confirmMigrations: MigrationConfirmation? = nil) throws { +func initializeChat(start: Bool, confirmStart: Bool = false, dbKey: String? = nil, refreshInvitations: Bool = true, confirmMigrations: MigrationConfirmation? = nil) throws { logger.debug("initializeChat") let m = ChatModel.shared + m.ctrlInitInProgress = true + defer { m.ctrlInitInProgress = false } (m.chatDbEncrypted, m.chatDbStatus) = chatMigrateInit(dbKey, confirmMigrations: confirmMigrations) if m.chatDbStatus != .ok { return } // If we migrated successfully means previous re-encryption process on database level finished successfully too @@ -1231,7 +1257,37 @@ func initializeChat(start: Bool, dbKey: String? = nil, refreshInvitations: Bool onboardingStageDefault.set(.step1_SimpleXInfo) privacyDeliveryReceiptsSet.set(true) m.onboardingStage = .step1_SimpleXInfo - } else if start { + } else if confirmStart { + showStartChatAfterRestartAlert { start in + do { + if start { AppChatState.shared.set(.active) } + try chatInitialized(start: start, refreshInvitations: refreshInvitations) + } catch let error { + logger.error("ChatInitialized error: \(error)") + } + } + } else { + try chatInitialized(start: start, refreshInvitations: refreshInvitations) + } +} + +func showStartChatAfterRestartAlert(result: @escaping (_ start: Bool) -> Void) { + AlertManager.shared.showAlert(Alert( + title: Text("Start chat?"), + message: Text("Chat is stopped. If you already used this database on another device, you should transfer it back before starting chat."), + primaryButton: .default(Text("Ok")) { + result(true) + }, + secondaryButton: .cancel { + result(false) + } + )) +} + +private func chatInitialized(start: Bool, refreshInvitations: Bool) throws { + let m = ChatModel.shared + if m.currentUser == nil { return } + if start { try startChat(refreshInvitations: refreshInvitations) } else { m.chatRunning = false @@ -1289,8 +1345,12 @@ private func changeActiveUser_(_ userId: Int64, viewPwd: String?) throws { try getUserChatData() } -func changeActiveUserAsync_(_ userId: Int64, viewPwd: String?) async throws { - let currentUser = try await apiSetActiveUserAsync(userId, viewPwd: viewPwd) +func changeActiveUserAsync_(_ userId: Int64?, viewPwd: String?) async throws { + let currentUser = if let userId = userId { + try await apiSetActiveUserAsync(userId, viewPwd: viewPwd) + } else { + try apiGetActiveUser() + } let users = try await listUsersAsync() await MainActor.run { let m = ChatModel.shared @@ -1299,7 +1359,7 @@ func changeActiveUserAsync_(_ userId: Int64, viewPwd: String?) async throws { } try await getUserChatDataAsync() await MainActor.run { - if var (_, invitation) = ChatModel.shared.callInvitations.first(where: { _, inv in inv.user.userId == userId }) { + if let currentUser = currentUser, var (_, invitation) = ChatModel.shared.callInvitations.first(where: { _, inv in inv.user.userId == userId }) { invitation.user = currentUser activateCall(invitation) } @@ -1315,14 +1375,21 @@ func getUserChatData() throws { } private func getUserChatDataAsync() async throws { - let userAddress = try await apiGetUserAddressAsync() - let chatItemTTL = try await getChatItemTTLAsync() - let chats = try await apiGetChatsAsync() - await MainActor.run { - let m = ChatModel.shared - m.userAddress = userAddress - m.chatItemTTL = chatItemTTL - m.chats = chats.map { Chat.init($0) } + let m = ChatModel.shared + if m.currentUser != nil { + let userAddress = try await apiGetUserAddressAsync() + let chatItemTTL = try await getChatItemTTLAsync() + let chats = try await apiGetChatsAsync() + await MainActor.run { + m.userAddress = userAddress + m.chatItemTTL = chatItemTTL + m.chats = chats.map { Chat.init($0) } + } + } else { + await MainActor.run { + m.userAddress = nil + m.chats = [] + } } } @@ -1481,7 +1548,7 @@ func processReceivedMsg(_ res: ChatResponse) async { } if let file = cItem.autoReceiveFile() { Task { - await receiveFile(user: user, fileId: file.fileId, encrypted: cItem.encryptLocalFile, auto: true) + await receiveFile(user: user, fileId: file.fileId, auto: true) } } if cItem.showNotification { @@ -1619,6 +1686,13 @@ func processReceivedMsg(_ res: ChatResponse) async { _ = m.upsertGroupMember(groupInfo, member) } } + case let .memberBlockedForAll(user, groupInfo, byMember: _, member: member, blocked: _): + if active(user) { + await MainActor.run { + m.updateGroup(groupInfo) + _ = m.upsertGroupMember(groupInfo, member) + } + } case let .newMemberContactReceivedInv(user, contact, _, _): if active(user) { await MainActor.run { diff --git a/apps/ios/Shared/Model/SuspendChat.swift b/apps/ios/Shared/Model/SuspendChat.swift index 0229bff2b3..4494adc0e8 100644 --- a/apps/ios/Shared/Model/SuspendChat.swift +++ b/apps/ios/Shared/Model/SuspendChat.swift @@ -107,26 +107,16 @@ func initChatAndMigrate(refreshInvitations: Bool = true) { let m = ChatModel.shared if (!m.chatInitialized) { m.v3DBMigration = v3DBMigrationDefault.get() - if AppChatState.shared.value == .stopped { - AlertManager.shared.showAlert(Alert( - title: Text("Start chat?"), - message: Text("Chat is stopped. If you already used this database on another device, you should transfer it back before starting chat."), - primaryButton: .default(Text("Ok")) { - AppChatState.shared.set(.active) - initialize(start: true) - }, - secondaryButton: .cancel { - initialize(start: false) - } - )) + if AppChatState.shared.value == .stopped && storeDBPassphraseGroupDefault.get() && kcDatabasePassword.get() != nil { + initialize(start: true, confirmStart: true) } else { initialize(start: true) } } - func initialize(start: Bool) { + func initialize(start: Bool, confirmStart: Bool = false) { do { - try initializeChat(start: m.v3DBMigration.startChat && start, refreshInvitations: refreshInvitations) + try initializeChat(start: m.v3DBMigration.startChat && start, confirmStart: m.v3DBMigration.startChat && confirmStart, refreshInvitations: refreshInvitations) } catch let error { AlertManager.shared.showAlertMsg( title: start ? "Error starting chat" : "Error opening chat", diff --git a/apps/ios/Shared/SimpleXApp.swift b/apps/ios/Shared/SimpleXApp.swift index 60d1cf7256..e5b98589a0 100644 --- a/apps/ios/Shared/SimpleXApp.swift +++ b/apps/ios/Shared/SimpleXApp.swift @@ -44,8 +44,10 @@ struct SimpleXApp: App { chatModel.appOpenUrl = url } .onAppear() { - DispatchQueue.main.asyncAfter(deadline: .now() + 0.15) { - initChatAndMigrate() + if kcAppPassword.get() == nil || kcSelfDestructPassword.get() == nil { + DispatchQueue.main.asyncAfter(deadline: .now() + 0.15) { + initChatAndMigrate() + } } } .onChange(of: scenePhase) { phase in diff --git a/apps/ios/Shared/Views/Chat/ChatItem/CIFileView.swift b/apps/ios/Shared/Views/Chat/ChatItem/CIFileView.swift index 4ae2296f46..c94ba3f830 100644 --- a/apps/ios/Shared/Views/Chat/ChatItem/CIFileView.swift +++ b/apps/ios/Shared/Views/Chat/ChatItem/CIFileView.swift @@ -52,7 +52,7 @@ struct CIFileView: View { private var itemInteractive: Bool { if let file = file { switch (file.fileStatus) { - case .sndStored: return false + case .sndStored: return file.fileProtocol == .local case .sndTransfer: return false case .sndComplete: return false case .sndCancelled: return false @@ -85,8 +85,7 @@ struct CIFileView: View { Task { logger.debug("CIFileView fileAction - in .rcvInvitation, in Task") if let user = m.currentUser { - let encrypted = privacyEncryptLocalFilesGroupDefault.get() - await receiveFile(user: user, fileId: file.fileId, encrypted: encrypted) + await receiveFile(user: user, fileId: file.fileId) } } } else { @@ -108,12 +107,18 @@ struct CIFileView: View { title: "Waiting for file", message: "File will be received when your contact is online, please wait or check later!" ) + case .local: () } case .rcvComplete: logger.debug("CIFileView fileAction - in .rcvComplete") if let fileSource = getLoadedFileSource(file) { saveCryptoFile(fileSource) } + case .sndStored: + logger.debug("CIFileView fileAction - in .sndStored") + if file.fileProtocol == .local, let fileSource = getLoadedFileSource(file) { + saveCryptoFile(fileSource) + } default: break } } @@ -126,11 +131,13 @@ struct CIFileView: View { switch file.fileProtocol { case .xftp: progressView() case .smp: fileIcon("doc.fill") + case .local: fileIcon("doc.fill") } case let .sndTransfer(sndProgress, sndTotal): switch file.fileProtocol { case .xftp: progressCircle(sndProgress, sndTotal) case .smp: progressView() + case .local: EmptyView() } case .sndComplete: fileIcon("doc.fill", innerIcon: "checkmark", innerIconSize: 10) case .sndCancelled: fileIcon("doc.fill", innerIcon: "xmark", innerIconSize: 10) diff --git a/apps/ios/Shared/Views/Chat/ChatItem/CIImageView.swift b/apps/ios/Shared/Views/Chat/ChatItem/CIImageView.swift index 9ae52ae01b..c7e89fc5ed 100644 --- a/apps/ios/Shared/Views/Chat/ChatItem/CIImageView.swift +++ b/apps/ios/Shared/Views/Chat/ChatItem/CIImageView.swift @@ -38,7 +38,7 @@ struct CIImageView: View { case .rcvInvitation: Task { if let user = m.currentUser { - await receiveFile(user: user, fileId: file.fileId, encrypted: chatItem.encryptLocalFile) + await receiveFile(user: user, fileId: file.fileId) } } case .rcvAccepted: @@ -53,6 +53,7 @@ struct CIImageView: View { title: "Waiting for image", message: "Image will be received when your contact is online, please wait or check later!" ) + case .local: () } case .rcvTransfer: () // ? case .rcvComplete: () // ? @@ -90,6 +91,7 @@ struct CIImageView: View { switch file.fileProtocol { case .xftp: progressView() case .smp: EmptyView() + case .local: EmptyView() } case .sndTransfer: progressView() case .sndComplete: fileIcon("checkmark", 10, 13) diff --git a/apps/ios/Shared/Views/Chat/ChatItem/CIVideoView.swift b/apps/ios/Shared/Views/Chat/ChatItem/CIVideoView.swift index be8b25a0fc..a824ddc49f 100644 --- a/apps/ios/Shared/Views/Chat/ChatItem/CIVideoView.swift +++ b/apps/ios/Shared/Views/Chat/ChatItem/CIVideoView.swift @@ -26,6 +26,8 @@ struct CIVideoView: View { @State private var player: AVPlayer? @State private var fullPlayer: AVPlayer? @State private var url: URL? + @State private var urlDecrypted: URL? + @State private var decryptionInProgress: Bool = false @State private var showFullScreenPlayer = false @State private var timeObserver: Any? = nil @State private var fullScreenTimeObserver: Any? = nil @@ -39,8 +41,12 @@ struct CIVideoView: View { self._videoWidth = videoWidth self.scrollProxy = scrollProxy if let url = getLoadedVideo(chatItem.file) { - self._player = State(initialValue: VideoPlayerView.getOrCreatePlayer(url, false)) - self._fullPlayer = State(initialValue: AVPlayer(url: url)) + let decrypted = chatItem.file?.fileSource?.cryptoArgs == nil ? url : chatItem.file?.fileSource?.decryptedGet() + self._urlDecrypted = State(initialValue: decrypted) + if let decrypted = decrypted { + self._player = State(initialValue: VideoPlayerView.getOrCreatePlayer(decrypted, false)) + self._fullPlayer = State(initialValue: AVPlayer(url: decrypted)) + } self._url = State(initialValue: url) } if let data = Data(base64Encoded: dropImagePrefix(image)), @@ -53,8 +59,10 @@ struct CIVideoView: View { let file = chatItem.file ZStack { ZStack(alignment: .topLeading) { - if let file = file, let preview = preview, let player = player, let url = url { - videoView(player, url, file, preview, duration) + if let file = file, let preview = preview, let player = player, let decrypted = urlDecrypted { + videoView(player, decrypted, file, preview, duration) + } else if let file = file, let defaultPreview = preview, file.loaded && urlDecrypted == nil { + videoViewEncrypted(file, defaultPreview, duration) } else if let data = Data(base64Encoded: dropImagePrefix(image)), let uiImage = UIImage(data: data) { imageView(uiImage) @@ -62,7 +70,7 @@ struct CIVideoView: View { if let file = file { switch file.fileStatus { case .rcvInvitation: - receiveFileIfValidSize(file: file, encrypted: false, receiveFile: receiveFile) + receiveFileIfValidSize(file: file, receiveFile: receiveFile) case .rcvAccepted: switch file.fileProtocol { case .xftp: @@ -75,6 +83,7 @@ struct CIVideoView: View { title: "Waiting for video", message: "Video will be received when your contact is online, please wait or check later!" ) + case .local: () } case .rcvTransfer: () // ? case .rcvComplete: () // ? @@ -88,7 +97,7 @@ struct CIVideoView: View { } if let file = file, case .rcvInvitation = file.fileStatus { Button { - receiveFileIfValidSize(file: file, encrypted: false, receiveFile: receiveFile) + receiveFileIfValidSize(file: file, receiveFile: receiveFile) } label: { playPauseIcon("play.fill") } @@ -96,12 +105,46 @@ struct CIVideoView: View { } } + private func videoViewEncrypted(_ file: CIFile, _ defaultPreview: UIImage, _ duration: Int) -> some View { + return ZStack(alignment: .topTrailing) { + ZStack(alignment: .center) { + let canBePlayed = !chatItem.chatDir.sent || file.fileStatus == CIFileStatus.sndComplete || (file.fileStatus == .sndStored && file.fileProtocol == .local) + imageView(defaultPreview) + .fullScreenCover(isPresented: $showFullScreenPlayer) { + if let decrypted = urlDecrypted { + fullScreenPlayer(decrypted) + } + } + .onTapGesture { + decrypt(file: file) { + showFullScreenPlayer = urlDecrypted != nil + } + } + if !decryptionInProgress { + Button { + decrypt(file: file) { + if let decrypted = urlDecrypted { + videoPlaying = true + player?.play() + } + } + } label: { + playPauseIcon(canBePlayed ? "play.fill" : "play.slash") + } + .disabled(!canBePlayed) + } else { + videoDecryptionProgress() + } + } + } + } + private func videoView(_ player: AVPlayer, _ url: URL, _ file: CIFile, _ preview: UIImage, _ duration: Int) -> some View { let w = preview.size.width <= preview.size.height ? maxWidth * 0.75 : maxWidth DispatchQueue.main.async { videoWidth = w } return ZStack(alignment: .topTrailing) { ZStack(alignment: .center) { - let canBePlayed = !chatItem.chatDir.sent || file.fileStatus == CIFileStatus.sndComplete + let canBePlayed = !chatItem.chatDir.sent || file.fileStatus == CIFileStatus.sndComplete || (file.fileStatus == .sndStored && file.fileProtocol == .local) VideoPlayerView(player: player, url: url, showControls: false) .frame(width: w, height: w * preview.size.height / preview.size.width) .onChange(of: m.stopPreviousRecPlay) { playingUrl in @@ -159,6 +202,16 @@ struct CIVideoView: View { .clipShape(Circle()) } + private func videoDecryptionProgress(_ color: Color = .white) -> some View { + ProgressView() + .progressViewStyle(.circular) + .frame(width: 12, height: 12) + .tint(color) + .frame(width: 40, height: 40) + .background(Color.black.opacity(0.35)) + .clipShape(Circle()) + } + private func durationProgress() -> some View { HStack { Text("\(durationText(videoPlaying ? progress : duration))") @@ -202,11 +255,13 @@ struct CIVideoView: View { switch file.fileProtocol { case .xftp: progressView() case .smp: EmptyView() + case .local: EmptyView() } case let .sndTransfer(sndProgress, sndTotal): switch file.fileProtocol { case .xftp: progressCircle(sndProgress, sndTotal) case .smp: progressView() + case .local: EmptyView() } case .sndComplete: fileIcon("checkmark", 10, 13) case .sndCancelled: fileIcon("xmark", 10, 13) @@ -257,10 +312,10 @@ struct CIVideoView: View { } // TODO encrypt: where file size is checked? - private func receiveFileIfValidSize(file: CIFile, encrypted: Bool, receiveFile: @escaping (User, Int64, Bool, Bool) async -> Void) { + private func receiveFileIfValidSize(file: CIFile, receiveFile: @escaping (User, Int64, Bool) async -> Void) { Task { if let user = m.currentUser { - await receiveFile(user, file.fileId, encrypted, false) + await receiveFile(user, file.fileId, false) } } } @@ -323,6 +378,22 @@ struct CIVideoView: View { } } + private func decrypt(file: CIFile, completed: (() -> Void)? = nil) { + if decryptionInProgress { return } + decryptionInProgress = true + Task { + urlDecrypted = await file.fileSource?.decryptedGetOrCreate(&ChatModel.shared.filesToDelete) + await MainActor.run { + if let decrypted = urlDecrypted { + player = VideoPlayerView.getOrCreatePlayer(decrypted, false) + fullPlayer = AVPlayer(url: decrypted) + } + decryptionInProgress = true + completed?() + } + } + } + private func addObserver(_ player: AVPlayer, _ url: URL) { timeObserver = player.addPeriodicTimeObserver(forInterval: CMTime(seconds: 0.01, preferredTimescale: CMTimeScale(NSEC_PER_SEC)), queue: .main) { time in if let item = player.currentItem { diff --git a/apps/ios/Shared/Views/Chat/ChatItem/CIVoiceView.swift b/apps/ios/Shared/Views/Chat/ChatItem/CIVoiceView.swift index 2e54ba4143..3aecb65ebd 100644 --- a/apps/ios/Shared/Views/Chat/ChatItem/CIVoiceView.swift +++ b/apps/ios/Shared/Views/Chat/ChatItem/CIVoiceView.swift @@ -221,7 +221,7 @@ struct VoiceMessagePlayer: View { Button { Task { if let user = chatModel.currentUser { - await receiveFile(user: user, fileId: recordingFile.fileId, encrypted: privacyEncryptLocalFilesGroupDefault.get()) + await receiveFile(user: user, fileId: recordingFile.fileId) } } } label: { diff --git a/apps/ios/Shared/Views/Chat/ChatItem/FramedItemView.swift b/apps/ios/Shared/Views/Chat/ChatItem/FramedItemView.swift index 51dfa3cb50..f7775a7cdd 100644 --- a/apps/ios/Shared/Views/Chat/ChatItem/FramedItemView.swift +++ b/apps/ios/Shared/Views/Chat/ChatItem/FramedItemView.swift @@ -9,6 +9,8 @@ import SwiftUI import SimpleXChat +let notesChatColorLight = Color(.sRGB, red: 0.27, green: 0.72, blue: 1, opacity: 0.21) +let notesChatColorDark = Color(.sRGB, red: 0.27, green: 0.72, blue: 1, opacity: 0.19) let sentColorLight = Color(.sRGB, red: 0.27, green: 0.72, blue: 1, opacity: 0.12) let sentColorDark = Color(.sRGB, red: 0.27, green: 0.72, blue: 1, opacity: 0.17) private let sentQuoteColorLight = Color(.sRGB, red: 0.27, green: 0.72, blue: 1, opacity: 0.11) @@ -28,7 +30,9 @@ struct FramedItemView: View { @State var metaColor = Color.secondary @State var showFullScreenImage = false @Binding var allowMenu: Bool - + @State private var showSecrets = false + @State private var showQuoteSecrets = false + @Binding var audioPlayer: AudioPlayer? @Binding var playbackState: VoiceMessagePlaybackState @Binding var playbackTime: TimeInterval? @@ -42,7 +46,9 @@ struct FramedItemView: View { framedItemHeader(icon: "flag", caption: Text("moderated by \(byGroupMember.displayName)").italic()) case .blocked: framedItemHeader(icon: "hand.raised", caption: Text("blocked").italic()) - default: + case .blockedByAdmin: + framedItemHeader(icon: "hand.raised", caption: Text("blocked by admin").italic()) + case .deleted: framedItemHeader(icon: "trash", caption: Text("marked deleted").italic()) } } else if chatItem.meta.isLive { @@ -252,10 +258,12 @@ struct FramedItemView: View { } private func ciQuotedMsgTextView(_ qi: CIQuote, lines: Int) -> some View { - MsgContentView(chat: chat, text: qi.text, formattedText: qi.formattedText) - .lineLimit(lines) - .font(.subheadline) - .padding(.bottom, 6) + toggleSecrets(qi.formattedText, $showQuoteSecrets, + MsgContentView(chat: chat, text: qi.text, formattedText: qi.formattedText, showSecrets: showQuoteSecrets) + .lineLimit(lines) + .font(.subheadline) + .padding(.bottom, 6) + ) } private func ciQuoteIconView(_ image: String) -> some View { @@ -278,13 +286,15 @@ struct FramedItemView: View { @ViewBuilder private func ciMsgContentView(_ ci: ChatItem) -> some View { let text = ci.meta.isLive ? ci.content.msgContent?.text ?? ci.text : ci.text let rtl = isRightToLeft(text) - let v = MsgContentView( + let ft = text == "" ? [] : ci.formattedText + let v = toggleSecrets(ft, $showSecrets, MsgContentView( chat: chat, text: text, - formattedText: text == "" ? [] : ci.formattedText, + formattedText: ft, meta: ci.meta, - rightToLeft: rtl - ) + rightToLeft: rtl, + showSecrets: showSecrets + )) .multilineTextAlignment(rtl ? .trailing : .leading) .padding(.vertical, 6) .padding(.horizontal, 12) @@ -298,7 +308,7 @@ struct FramedItemView: View { v } } - + @ViewBuilder private func ciFileView(_ ci: ChatItem, _ text: String) -> some View { CIFileView(file: chatItem.file, edited: chatItem.meta.itemEdited) .overlay(DetermineWidth()) @@ -318,6 +328,14 @@ struct FramedItemView: View { } } +@ViewBuilder func toggleSecrets(_ ft: [FormattedText]?, _ showSecrets: Binding, _ v: V) -> some View { + if let ft = ft, ft.contains(where: { $0.isSecret }) { + v.onTapGesture { showSecrets.wrappedValue.toggle() } + } else { + v + } +} + func isRightToLeft(_ s: String) -> Bool { if let lang = CFStringTokenizerCopyBestStringLanguage(s as CFString, CFRange(location: 0, length: min(s.count, 80))) { return NSLocale.characterDirection(forLanguage: lang as String) == .rightToLeft diff --git a/apps/ios/Shared/Views/Chat/ChatItem/MarkedDeletedItemView.swift b/apps/ios/Shared/Views/Chat/ChatItem/MarkedDeletedItemView.swift index c6af95e6f6..dfa4a97fc2 100644 --- a/apps/ios/Shared/Views/Chat/ChatItem/MarkedDeletedItemView.swift +++ b/apps/ios/Shared/Views/Chat/ChatItem/MarkedDeletedItemView.swift @@ -33,6 +33,7 @@ struct MarkedDeletedItemView: View { var i = m.getChatItemIndex(chatItem) { var moderated = 0 var blocked = 0 + var blockedByAdmin = 0 var deleted = 0 var moderatedBy: Set = [] while i < m.reversedChatItems.count, @@ -44,16 +45,19 @@ struct MarkedDeletedItemView: View { moderated += 1 moderatedBy.insert(byGroupMember.displayName) case .blocked: blocked += 1 + case .blockedByAdmin: blockedByAdmin += 1 case .deleted: deleted += 1 } i += 1 } - let total = moderated + blocked + deleted + let total = moderated + blocked + blockedByAdmin + deleted return total <= 1 ? markedDeletedText : total == moderated ? "\(total) messages moderated by \(moderatedBy.joined(separator: ", "))" - : total == blocked + : total == blockedByAdmin + ? "\(total) messages blocked by admin" + : total == blocked + blockedByAdmin ? "\(total) messages blocked" : "\(total) messages marked deleted" } else { @@ -65,7 +69,8 @@ struct MarkedDeletedItemView: View { switch chatItem.meta.itemDeleted { case let .moderated(_, byGroupMember): "moderated by \(byGroupMember.displayName)" case .blocked: "blocked" - default: "marked deleted" + case .blockedByAdmin: "blocked by admin" + case .deleted, nil: "marked deleted" } } } diff --git a/apps/ios/Shared/Views/Chat/ChatItem/MsgContentView.swift b/apps/ios/Shared/Views/Chat/ChatItem/MsgContentView.swift index d0d2bdf3dd..ccd7ac0a12 100644 --- a/apps/ios/Shared/Views/Chat/ChatItem/MsgContentView.swift +++ b/apps/ios/Shared/Views/Chat/ChatItem/MsgContentView.swift @@ -9,7 +9,7 @@ import SwiftUI import SimpleXChat -private let uiLinkColor = UIColor(red: 0, green: 0.533, blue: 1, alpha: 1) +let uiLinkColor = UIColor(red: 0, green: 0.533, blue: 1, alpha: 1) private let noTyping = Text(" ") @@ -31,6 +31,7 @@ struct MsgContentView: View { var sender: String? = nil var meta: CIMeta? = nil var rightToLeft = false + var showSecrets: Bool @State private var typingIdx = 0 @State private var timer: Timer? @@ -62,7 +63,7 @@ struct MsgContentView: View { } private func msgContentView() -> Text { - var v = messageText(text, formattedText, sender) + var v = messageText(text, formattedText, sender, showSecrets: showSecrets) if let mt = meta { if mt.isLive { v = v + typingIndicator(mt.recent) @@ -84,14 +85,14 @@ struct MsgContentView: View { } } -func messageText(_ text: String, _ formattedText: [FormattedText]?, _ sender: String?, icon: String? = nil, preview: Bool = false) -> Text { +func messageText(_ text: String, _ formattedText: [FormattedText]?, _ sender: String?, icon: String? = nil, preview: Bool = false, showSecrets: Bool) -> Text { let s = text var res: Text if let ft = formattedText, ft.count > 0 && ft.count <= 200 { - res = formatText(ft[0], preview) + res = formatText(ft[0], preview, showSecret: showSecrets) var i = 1 while i < ft.count { - res = res + formatText(ft[i], preview) + res = res + formatText(ft[i], preview, showSecret: showSecrets) i = i + 1 } } else { @@ -110,7 +111,7 @@ func messageText(_ text: String, _ formattedText: [FormattedText]?, _ sender: St } } -private func formatText(_ ft: FormattedText, _ preview: Bool) -> Text { +private func formatText(_ ft: FormattedText, _ preview: Bool, showSecret: Bool) -> Text { let t = ft.text if let f = ft.format { switch (f) { @@ -118,7 +119,13 @@ private func formatText(_ ft: FormattedText, _ preview: Bool) -> Text { case .italic: return Text(t).italic() case .strikeThrough: return Text(t).strikethrough() case .snippet: return Text(t).font(.body.monospaced()) - case .secret: return Text(t).foregroundColor(.clear).underline(color: .primary) + case .secret: return + showSecret + ? Text(t) + : Text(AttributedString(t, attributes: AttributeContainer([ + .foregroundColor: UIColor.clear as Any, + .backgroundColor: UIColor.secondarySystemFill as Any + ]))) case let .colored(color): return Text(t).foregroundColor(color.uiColor) case .uri: return linkText(t, t, preview, prefix: "") case let .simplexLink(linkType, simplexUri, smpHosts): @@ -144,7 +151,7 @@ private func linkText(_ s: String, _ link: String, _ preview: Bool, prefix: Stri ]))).underline() } -private func simplexLinkText(_ linkType: SimplexLinkType, _ smpHosts: [String]) -> String { +func simplexLinkText(_ linkType: SimplexLinkType, _ smpHosts: [String]) -> String { linkType.description + " " + "(via \(smpHosts.first ?? "?"))" } @@ -156,7 +163,8 @@ struct MsgContentView_Previews: PreviewProvider { text: chatItem.text, formattedText: chatItem.formattedText, sender: chatItem.memberDisplayName, - meta: chatItem.meta + meta: chatItem.meta, + showSecrets: false ) .environmentObject(Chat.sampleData) } diff --git a/apps/ios/Shared/Views/Chat/ChatItemInfoView.swift b/apps/ios/Shared/Views/Chat/ChatItemInfoView.swift index 83c4cdcda6..8dd43cc01b 100644 --- a/apps/ios/Shared/Views/Chat/ChatItemInfoView.swift +++ b/apps/ios/Shared/Views/Chat/ChatItemInfoView.swift @@ -53,7 +53,9 @@ struct ChatItemInfoView: View { } private var title: String { - ci.chatDir.sent + ci.localNote + ? NSLocalizedString("Saved message", comment: "message info title") + : ci.chatDir.sent ? NSLocalizedString("Sent message", comment: "message info title") : NSLocalizedString("Received message", comment: "message info title") } @@ -110,7 +112,11 @@ struct ChatItemInfoView: View { .bold() .padding(.bottom) - infoRow("Sent at", localTimestamp(meta.itemTs)) + if ci.localNote { + infoRow("Created at", localTimestamp(meta.itemTs)) + } else { + infoRow("Sent at", localTimestamp(meta.itemTs)) + } if !ci.chatDir.sent { infoRow("Received at", localTimestamp(meta.createdAt)) } @@ -168,7 +174,6 @@ struct ChatItemInfoView: View { @ViewBuilder private func itemVersionView(_ itemVersion: ChatItemVersion, _ maxWidth: CGFloat, current: Bool) -> some View { VStack(alignment: .leading, spacing: 4) { textBubble(itemVersion.msgContent.text, itemVersion.formattedText, nil) - .allowsHitTesting(false) .padding(.horizontal, 12) .padding(.vertical, 6) .background(chatItemFrameColor(ci, colorScheme)) @@ -198,7 +203,7 @@ struct ChatItemInfoView: View { @ViewBuilder private func textBubble(_ text: String, _ formattedText: [FormattedText]?, _ sender: String? = nil) -> some View { if text != "" { - messageText(text, formattedText, sender) + TextBubble(text: text, formattedText: formattedText, sender: sender) } else { Text("no text") .italic() @@ -206,6 +211,17 @@ struct ChatItemInfoView: View { } } + private struct TextBubble: View { + var text: String + var formattedText: [FormattedText]? + var sender: String? = nil + @State private var showSecrets = false + + var body: some View { + toggleSecrets(formattedText, $showSecrets, messageText(text, formattedText, sender, showSecrets: showSecrets)) + } + } + @ViewBuilder private func quoteTab(_ qi: CIQuote) -> some View { GeometryReader { g in let maxWidth = (g.size.width - 32) * 0.84 @@ -227,7 +243,6 @@ struct ChatItemInfoView: View { @ViewBuilder private func quotedMsgView(_ qi: CIQuote, _ maxWidth: CGFloat) -> some View { VStack(alignment: .leading, spacing: 4) { textBubble(qi.text, qi.formattedText, qi.getSender(nil)) - .allowsHitTesting(false) .padding(.horizontal, 12) .padding(.vertical, 6) .background(quotedMsgFrameColor(qi, colorScheme)) @@ -341,7 +356,12 @@ struct ChatItemInfoView: View { private func itemInfoShareText() -> String { let meta = ci.meta var shareText: [String] = [String.localizedStringWithFormat(NSLocalizedString("# %@", comment: "copied message info title, # "), title), ""] - shareText += [String.localizedStringWithFormat(NSLocalizedString("Sent at: %@", comment: "copied message info"), localTimestamp(meta.itemTs))] + shareText += [String.localizedStringWithFormat( + ci.localNote + ? NSLocalizedString("Created at: %@", comment: "copied message info") + : NSLocalizedString("Sent at: %@", comment: "copied message info"), + localTimestamp(meta.itemTs)) + ] if !ci.chatDir.sent { shareText += [String.localizedStringWithFormat(NSLocalizedString("Received at: %@", comment: "copied message info"), localTimestamp(meta.createdAt))] } diff --git a/apps/ios/Shared/Views/Chat/ChatItemView.swift b/apps/ios/Shared/Views/Chat/ChatItemView.swift index 657df60654..8f67a8f737 100644 --- a/apps/ios/Shared/Views/Chat/ChatItemView.swift +++ b/apps/ios/Shared/Views/Chat/ChatItemView.swift @@ -109,6 +109,7 @@ struct ChatItemContentView<Content: View>: View { case let .rcvGroupFeatureRejected(feature): chatFeatureView(feature, .red) case .sndModerated: deletedItemView() case .rcvModerated: deletedItemView() + case .rcvBlocked: deletedItemView() case let .invalidJSON(json): CIInvalidJSONView(json: json) } } diff --git a/apps/ios/Shared/Views/Chat/ChatView.swift b/apps/ios/Shared/Views/Chat/ChatView.swift index 6e2c0c1555..af53e7e476 100644 --- a/apps/ios/Shared/Views/Chat/ChatView.swift +++ b/apps/ios/Shared/Views/Chat/ChatView.swift @@ -151,6 +151,8 @@ struct ChatView: View { ) ) } + } else if case .local = cInfo { + ChatInfoToolbar(chat: chat) } } ToolbarItem(placement: .navigationBarTrailing) { @@ -205,6 +207,8 @@ struct ChatView: View { Image(systemName: "ellipsis") } } + case .local: + searchButton() default: EmptyView() } @@ -250,8 +254,8 @@ struct ChatView: View { } private func searchToolbar() -> some View { - HStack { - HStack { + HStack(spacing: 12) { + HStack(spacing: 4) { Image(systemName: "magnifyingglass") TextField("Search", text: $searchText) .focused($searchFocussed) @@ -264,9 +268,9 @@ struct ChatView: View { Image(systemName: "xmark.circle.fill").opacity(searchText == "" ? 0 : 1) } } - .padding(EdgeInsets(top: 8, leading: 6, bottom: 8, trailing: 6)) + .padding(EdgeInsets(top: 7, leading: 7, bottom: 7, trailing: 7)) .foregroundColor(.secondary) - .background(Color(.secondarySystemBackground)) + .background(Color(.tertiarySystemFill)) .cornerRadius(10.0) Button ("Cancel") { @@ -636,7 +640,7 @@ struct ChatView: View { Button("Delete for me", role: .destructive) { deleteMessage(.cidmInternal) } - if let di = deletingItem, di.meta.editable { + if let di = deletingItem, di.meta.editable && !di.localNote { Button(broadcastDeleteButtonText, role: .destructive) { deleteMessage(.cidmBroadcast) } @@ -720,7 +724,7 @@ struct ChatView: View { } menu.append(rm) } - if ci.meta.itemDeleted == nil && !ci.isLiveDummy && !live { + if ci.meta.itemDeleted == nil && !ci.isLiveDummy && !live && !ci.localNote { menu.append(replyUIAction(ci)) } let fileSource = getLoadedFileSource(ci.file) @@ -748,9 +752,9 @@ struct ChatView: View { if revealed { menu.append(hideUIAction()) } - if ci.meta.itemDeleted == nil, + if ci.meta.itemDeleted == nil && !ci.localNote, let file = ci.file, - let cancelAction = file.cancelAction { + let cancelAction = file.cancelAction { menu.append(cancelFileUIAction(file.fileId, cancelAction)) } if !live || !ci.meta.isLive { diff --git a/apps/ios/Shared/Views/Chat/ComposeMessage/ComposeView.swift b/apps/ios/Shared/Views/Chat/ComposeMessage/ComposeView.swift index d089c7d6fe..b597926093 100644 --- a/apps/ios/Shared/Views/Chat/ComposeMessage/ComposeView.swift +++ b/apps/ios/Shared/Views/Chat/ComposeMessage/ComposeView.swift @@ -295,7 +295,7 @@ struct ComposeView: View { sendMessage(ttl: ttl) resetLinkPreview() }, - sendLiveMessage: sendLiveMessage, + sendLiveMessage: chat.chatInfo.chatType != .local ? sendLiveMessage : nil, updateLiveMessage: updateLiveMessage, cancelLiveMessage: { composeState.liveMessage = nil @@ -689,7 +689,7 @@ struct ComposeView: View { let file = voiceCryptoFile(recordingFileName) sent = await send(.voice(text: msgText, duration: duration), quoted: quoted, file: file, ttl: ttl) case let .filePreview(_, file): - if let savedFile = saveFileFromURL(file, encrypted: privacyEncryptLocalFilesGroupDefault.get()) { + if let savedFile = saveFileFromURL(file) { sent = await send(.file(msgText), quoted: quoted, file: savedFile, live: live, ttl: ttl) } } @@ -792,15 +792,17 @@ struct ComposeView: View { } func send(_ mc: MsgContent, quoted: Int64?, file: CryptoFile? = nil, live: Bool = false, ttl: Int?) async -> ChatItem? { - if let chatItem = await apiSendMessage( - type: chat.chatInfo.chatType, - id: chat.chatInfo.apiId, - file: file, - quotedItemId: quoted, - msg: mc, - live: live, - ttl: ttl - ) { + if let chatItem = chat.chatInfo.chatType == .local + ? await apiCreateChatItem(noteFolderId: chat.chatInfo.apiId, file: file, msg: mc) + : await apiSendMessage( + type: chat.chatInfo.chatType, + id: chat.chatInfo.apiId, + file: file, + quotedItemId: quoted, + msg: mc, + live: live, + ttl: ttl + ) { await MainActor.run { chatModel.removeLiveDummy(animated: false) chatModel.addChatItem(chat.chatInfo, chatItem) diff --git a/apps/ios/Shared/Views/Chat/ComposeMessage/ContextItemView.swift b/apps/ios/Shared/Views/Chat/ComposeMessage/ContextItemView.swift index 868ae3274a..3eb128cded 100644 --- a/apps/ios/Shared/Views/Chat/ComposeMessage/ContextItemView.swift +++ b/apps/ios/Shared/Views/Chat/ComposeMessage/ContextItemView.swift @@ -51,7 +51,8 @@ struct ContextItemView: View { MsgContentView( chat: chat, text: contextItem.text, - formattedText: contextItem.formattedText + formattedText: contextItem.formattedText, + showSecrets: false ) .multilineTextAlignment(isRightToLeft(contextItem.text) ? .trailing : .leading) .lineLimit(lines) diff --git a/apps/ios/Shared/Views/Chat/ContactPreferencesView.swift b/apps/ios/Shared/Views/Chat/ContactPreferencesView.swift index ff1892d996..57007fff3f 100644 --- a/apps/ios/Shared/Views/Chat/ContactPreferencesView.swift +++ b/apps/ios/Shared/Views/Chat/ContactPreferencesView.swift @@ -116,7 +116,6 @@ struct ContactPreferencesView: View { private func featureFooter(_ feature: ChatFeature, _ enabled: FeatureEnabled) -> some View { Text(feature.enabledDescription(enabled)) - .frame(height: 36, alignment: .topLeading) } private func savePreferences() { diff --git a/apps/ios/Shared/Views/Chat/Group/GroupChatInfoView.swift b/apps/ios/Shared/Views/Chat/Group/GroupChatInfoView.swift index 09ead880ad..3879e78d3d 100644 --- a/apps/ios/Shared/Views/Chat/Group/GroupChatInfoView.swift +++ b/apps/ios/Shared/Views/Chat/Group/GroupChatInfoView.swift @@ -36,6 +36,8 @@ struct GroupChatInfoView: View { case largeGroupReceiptsDisabled case blockMemberAlert(mem: GroupMember) case unblockMemberAlert(mem: GroupMember) + case blockForAllAlert(mem: GroupMember) + case unblockForAllAlert(mem: GroupMember) case removeMemberAlert(mem: GroupMember) case error(title: LocalizedStringKey, error: LocalizedStringKey) @@ -48,6 +50,8 @@ struct GroupChatInfoView: View { case .largeGroupReceiptsDisabled: return "largeGroupReceiptsDisabled" case let .blockMemberAlert(mem): return "blockMemberAlert \(mem.groupMemberId)" case let .unblockMemberAlert(mem): return "unblockMemberAlert \(mem.groupMemberId)" + case let .blockForAllAlert(mem): return "blockForAllAlert \(mem.groupMemberId)" + case let .unblockForAllAlert(mem): return "unblockForAllAlert \(mem.groupMemberId)" case let .removeMemberAlert(mem): return "removeMemberAlert \(mem.groupMemberId)" case let .error(title, _): return "error \(title)" } @@ -143,6 +147,8 @@ struct GroupChatInfoView: View { case .largeGroupReceiptsDisabled: return largeGroupReceiptsDisabledAlert() case let .blockMemberAlert(mem): return blockMemberAlert(groupInfo, mem) case let .unblockMemberAlert(mem): return unblockMemberAlert(groupInfo, mem) + case let .blockForAllAlert(mem): return blockForAllAlert(groupInfo, mem) + case let .unblockForAllAlert(mem): return unblockForAllAlert(groupInfo, mem) case let .removeMemberAlert(mem): return removeMemberAlert(mem) case let .error(title, error): return Alert(title: Text(title), message: Text(error)) } @@ -226,13 +232,10 @@ struct GroupChatInfoView: View { .foregroundColor(.secondary) } Spacer() - let role = member.memberRole - if role == .owner || role == .admin { - Text(member.memberRole.text) - .foregroundColor(.secondary) - } + memberInfo(member) } + // revert from this: if user { v } else if member.canBeRemoved(groupInfo: groupInfo) { @@ -240,6 +243,43 @@ struct GroupChatInfoView: View { } else { blockSwipe(member, v) } + // revert to this: vvv +// if user { +// v +// } else if groupInfo.membership.memberRole >= .admin { +// // TODO if there are more actions, refactor with lists of swipeActions +// let canBlockForAll = member.canBlockForAll(groupInfo: groupInfo) +// let canRemove = member.canBeRemoved(groupInfo: groupInfo) +// if canBlockForAll && canRemove { +// removeSwipe(member, blockForAllSwipe(member, v)) +// } else if canBlockForAll { +// blockForAllSwipe(member, v) +// } else if canRemove { +// removeSwipe(member, v) +// } else { +// v +// } +// } else { +// if !member.blockedByAdmin { +// blockSwipe(member, v) +// } else { +// v +// } +// } + // ^^^ + } + + @ViewBuilder private func memberInfo(_ member: GroupMember) -> some View { + if member.blocked { + Text("blocked") + .foregroundColor(.secondary) + } else { + let role = member.memberRole + if [.owner, .admin, .observer].contains(role) { + Text(member.memberRole.text) + .foregroundColor(.secondary) + } + } } private func blockSwipe<V: View>(_ member: GroupMember, _ v: V) -> some View { @@ -260,6 +300,24 @@ struct GroupChatInfoView: View { } } + private func blockForAllSwipe<V: View>(_ member: GroupMember, _ v: V) -> some View { + v.swipeActions(edge: .leading) { + if member.blockedByAdmin { + Button { + alert = .unblockForAllAlert(mem: member) + } label: { + Label("Unblock for all", systemImage: "hand.raised.slash").foregroundColor(.accentColor) + } + } else { + Button { + alert = .blockForAllAlert(mem: member) + } label: { + Label("Block for all", systemImage: "hand.raised").foregroundColor(.secondary) + } + } + } + } + private func removeSwipe<V: View>(_ member: GroupMember, _ v: V) -> some View { v.swipeActions(edge: .trailing) { Button(role: .destructive) { diff --git a/apps/ios/Shared/Views/Chat/Group/GroupLinkView.swift b/apps/ios/Shared/Views/Chat/Group/GroupLinkView.swift index bf2179bea4..c782e2a717 100644 --- a/apps/ios/Shared/Views/Chat/Group/GroupLinkView.swift +++ b/apps/ios/Shared/Views/Chat/Group/GroupLinkView.swift @@ -18,6 +18,7 @@ struct GroupLinkView: View { var linkCreatedCb: (() -> Void)? = nil @State private var creatingLink = false @State private var alert: GroupLinkAlert? + @State private var shouldCreate = true private enum GroupLinkAlert: Identifiable { case deleteLink @@ -70,6 +71,7 @@ struct GroupLinkView: View { } .frame(height: 36) SimpleXLinkQRCode(uri: groupLink) + .id("simplex-qrcode-view-for-\(groupLink)") Button { showShareSheet(items: [simplexChatLink(groupLink)]) } label: { @@ -125,9 +127,10 @@ struct GroupLinkView: View { } } .onAppear { - if groupLink == nil && !creatingLink { + if groupLink == nil && !creatingLink && shouldCreate { createGroupLink() } + shouldCreate = false } } } diff --git a/apps/ios/Shared/Views/Chat/Group/GroupMemberInfoView.swift b/apps/ios/Shared/Views/Chat/Group/GroupMemberInfoView.swift index 7e336c3328..d2b0f77393 100644 --- a/apps/ios/Shared/Views/Chat/Group/GroupMemberInfoView.swift +++ b/apps/ios/Shared/Views/Chat/Group/GroupMemberInfoView.swift @@ -27,6 +27,8 @@ struct GroupMemberInfoView: View { enum GroupMemberInfoViewAlert: Identifiable { case blockMemberAlert(mem: GroupMember) case unblockMemberAlert(mem: GroupMember) + case blockForAllAlert(mem: GroupMember) + case unblockForAllAlert(mem: GroupMember) case removeMemberAlert(mem: GroupMember) case changeMemberRoleAlert(mem: GroupMember, role: GroupMemberRole) case switchAddressAlert @@ -39,6 +41,8 @@ struct GroupMemberInfoView: View { switch self { case let .blockMemberAlert(mem): return "blockMemberAlert \(mem.groupMemberId)" case let .unblockMemberAlert(mem): return "unblockMemberAlert \(mem.groupMemberId)" + case let .blockForAllAlert(mem): return "blockForAllAlert \(mem.groupMemberId)" + case let .unblockForAllAlert(mem): return "unblockForAllAlert \(mem.groupMemberId)" case let .removeMemberAlert(mem): return "removeMemberAlert \(mem.groupMemberId)" case let .changeMemberRoleAlert(mem, role): return "changeMemberRoleAlert \(mem.groupMemberId) \(role.rawValue)" case .switchAddressAlert: return "switchAddressAlert" @@ -164,6 +168,7 @@ struct GroupMemberInfoView: View { } } + // revert from this: Section { if member.memberSettings.showMessages { blockMemberButton(member) @@ -171,9 +176,16 @@ struct GroupMemberInfoView: View { unblockMemberButton(member) } if member.canBeRemoved(groupInfo: groupInfo) { - removeMemberButton(member) + removeMemberButton(member) } } + // revert to this: vvv +// if groupInfo.membership.memberRole >= .admin { +// adminDestructiveSection(member) +// } else { +// nonAdminBlockSection(member) +// } + // ^^^ if developerTools { Section("For console") { @@ -216,6 +228,8 @@ struct GroupMemberInfoView: View { switch(alertItem) { case let .blockMemberAlert(mem): return blockMemberAlert(groupInfo, mem) case let .unblockMemberAlert(mem): return unblockMemberAlert(groupInfo, mem) + case let .blockForAllAlert(mem): return blockForAllAlert(groupInfo, mem) + case let .unblockForAllAlert(mem): return unblockForAllAlert(groupInfo, mem) case let .removeMemberAlert(mem): return removeMemberAlert(mem) case let .changeMemberRoleAlert(mem, _): return changeMemberRoleAlert(mem) case .switchAddressAlert: return switchAddressAlert(switchMemberAddress) @@ -385,6 +399,55 @@ struct GroupMemberInfoView: View { } } + @ViewBuilder private func adminDestructiveSection(_ mem: GroupMember) -> some View { + let canBlockForAll = mem.canBlockForAll(groupInfo: groupInfo) + let canRemove = mem.canBeRemoved(groupInfo: groupInfo) + if canBlockForAll || canRemove { + Section { + if canBlockForAll { + if mem.blockedByAdmin { + unblockForAllButton(mem) + } else { + blockForAllButton(mem) + } + } + if canRemove { + removeMemberButton(mem) + } + } + } + } + + private func nonAdminBlockSection(_ mem: GroupMember) -> some View { + Section { + if mem.blockedByAdmin { + Label("Blocked by admin", systemImage: "hand.raised") + .foregroundColor(.secondary) + } else if mem.memberSettings.showMessages { + blockMemberButton(mem) + } else { + unblockMemberButton(mem) + } + } + } + + private func blockForAllButton(_ mem: GroupMember) -> some View { + Button(role: .destructive) { + alert = .blockForAllAlert(mem: mem) + } label: { + Label("Block for all", systemImage: "hand.raised") + .foregroundColor(.red) + } + } + + private func unblockForAllButton(_ mem: GroupMember) -> some View { + Button { + alert = .unblockForAllAlert(mem: mem) + } label: { + Label("Unblock for all", systemImage: "hand.raised.slash") + } + } + private func blockMemberButton(_ mem: GroupMember) -> some View { Button(role: .destructive) { alert = .blockMemberAlert(mem: mem) @@ -560,6 +623,41 @@ func updateMemberSettings(_ gInfo: GroupInfo, _ member: GroupMember, _ memberSet } } +func blockForAllAlert(_ gInfo: GroupInfo, _ mem: GroupMember) -> Alert { + Alert( + title: Text("Block member for all?"), + message: Text("All new messages from \(mem.chatViewName) will be hidden!"), + primaryButton: .destructive(Text("Block for all")) { + blockMemberForAll(gInfo, mem, true) + }, + secondaryButton: .cancel() + ) +} + +func unblockForAllAlert(_ gInfo: GroupInfo, _ mem: GroupMember) -> Alert { + Alert( + title: Text("Unblock member for all?"), + message: Text("Messages from \(mem.chatViewName) will be shown!"), + primaryButton: .default(Text("Unblock for all")) { + blockMemberForAll(gInfo, mem, false) + }, + secondaryButton: .cancel() + ) +} + +func blockMemberForAll(_ gInfo: GroupInfo, _ member: GroupMember, _ blocked: Bool) { + Task { + do { + let updatedMember = try await apiBlockMemberForAll(gInfo.groupId, member.groupMemberId, blocked) + await MainActor.run { + _ = ChatModel.shared.upsertGroupMember(gInfo, updatedMember) + } + } catch let error { + logger.error("apiBlockMemberForAll error: \(responseError(error))") + } + } +} + struct GroupMemberInfoView_Previews: PreviewProvider { static var previews: some View { GroupMemberInfoView( diff --git a/apps/ios/Shared/Views/Chat/Group/GroupPreferencesView.swift b/apps/ios/Shared/Views/Chat/Group/GroupPreferencesView.swift index 860a6febb0..d88bdfa4a4 100644 --- a/apps/ios/Shared/Views/Chat/Group/GroupPreferencesView.swift +++ b/apps/ios/Shared/Views/Chat/Group/GroupPreferencesView.swift @@ -28,6 +28,7 @@ struct GroupPreferencesView: View { featureSection(.reactions, $preferences.reactions.enable) featureSection(.voice, $preferences.voice.enable) featureSection(.files, $preferences.files.enable) + featureSection(.history, $preferences.history.enable) if groupInfo.canEdit { Section { @@ -96,7 +97,6 @@ struct GroupPreferencesView: View { } } footer: { Text(feature.enableDescription(enableFeature.wrappedValue, groupInfo.canEdit)) - .frame(height: 36, alignment: .topLeading) } } diff --git a/apps/ios/Shared/Views/Chat/Group/GroupWelcomeView.swift b/apps/ios/Shared/Views/Chat/Group/GroupWelcomeView.swift index 0e47d9dddf..e5ff644a91c 100644 --- a/apps/ios/Shared/Views/Chat/Group/GroupWelcomeView.swift +++ b/apps/ios/Shared/Views/Chat/Group/GroupWelcomeView.swift @@ -53,8 +53,7 @@ struct GroupWelcomeView: View { } private func textPreview() -> some View { - messageText(welcomeText, parseSimpleXMarkdown(welcomeText), nil) - .allowsHitTesting(false) + messageText(welcomeText, parseSimpleXMarkdown(welcomeText), nil, showSecrets: false) .frame(minHeight: 140, alignment: .topLeading) .frame(maxWidth: .infinity, alignment: .leading) } diff --git a/apps/ios/Shared/Views/ChatList/ChatHelp.swift b/apps/ios/Shared/Views/ChatList/ChatHelp.swift index 7741512432..2435c9a4f5 100644 --- a/apps/ios/Shared/Views/ChatList/ChatHelp.swift +++ b/apps/ios/Shared/Views/ChatList/ChatHelp.swift @@ -11,7 +11,7 @@ import SwiftUI struct ChatHelp: View { @EnvironmentObject var chatModel: ChatModel @Binding var showSettings: Bool - @State private var showAddChat = false + @State private var newChatMenuOption: NewChatMenuOption? = nil var body: some View { ScrollView { chatHelp() } @@ -39,13 +39,12 @@ struct ChatHelp: View { HStack(spacing: 8) { Text("Tap button ") - NewChatButton(showAddChat: $showAddChat) + NewChatMenuButton(newChatMenuOption: $newChatMenuOption) Text("above, then choose:") } - Text("**Create link / QR code** for your contact to use.") - Text("**Paste received link** or open it in the browser and tap **Open in mobile app**.") - Text("**Scan QR code**: to connect to your contact in person or via video call.") + Text("**Add contact**: to create a new invitation link, or connect via a link you received.") + Text("**Create group**: to create a new group.") } .padding(.top, 24) diff --git a/apps/ios/Shared/Views/ChatList/ChatListNavLink.swift b/apps/ios/Shared/Views/ChatList/ChatListNavLink.swift index 18464b3bb5..7fbc1e4ac8 100644 --- a/apps/ios/Shared/Views/ChatList/ChatListNavLink.swift +++ b/apps/ios/Shared/Views/ChatList/ChatListNavLink.swift @@ -44,6 +44,8 @@ struct ChatListNavLink: View { contactNavLink(contact) case let .group(groupInfo): groupNavLink(groupInfo) + case let .local(noteFolder): + noteFolderNavLink(noteFolder) case let .contactRequest(cReq): contactRequestNavLink(cReq) case let .contactConnection(cConn): @@ -195,6 +197,24 @@ struct ChatListNavLink: View { } } + @ViewBuilder private func noteFolderNavLink(_ noteFolder: NoteFolder) -> some View { + NavLinkPlain( + tag: chat.chatInfo.id, + selection: $chatModel.chatId, + label: { ChatPreviewView(chat: chat, progressByTimeout: Binding.constant(false)) }, + disabled: !noteFolder.ready + ) + .frame(height: rowHeights[dynamicTypeSize]) + .swipeActions(edge: .leading, allowsFullSwipe: true) { + markReadButton() + } + .swipeActions(edge: .trailing, allowsFullSwipe: true) { + if !chat.chatItems.isEmpty { + clearNoteFolderButton() + } + } + } + private func joinGroupButton() -> some View { Button { inProgress = true @@ -253,6 +273,15 @@ struct ChatListNavLink: View { .tint(Color.orange) } + private func clearNoteFolderButton() -> some View { + Button { + AlertManager.shared.showAlert(clearNoteFolderAlert()) + } label: { + Label("Clear", systemImage: "gobackward") + } + .tint(Color.orange) + } + private func leaveGroupChatButton(_ groupInfo: GroupInfo) -> some View { Button { AlertManager.shared.showAlert(leaveGroupAlert(groupInfo)) @@ -357,6 +386,17 @@ struct ChatListNavLink: View { ) } + private func clearNoteFolderAlert() -> Alert { + Alert( + title: Text("Clear private notes?"), + message: Text("All messages will be deleted - this cannot be undone!"), + primaryButton: .destructive(Text("Clear")) { + Task { await clearChat(chat) } + }, + secondaryButton: .cancel() + ) + } + private func leaveGroupAlert(_ groupInfo: GroupInfo) -> Alert { Alert( title: Text("Leave group?"), diff --git a/apps/ios/Shared/Views/ChatList/ChatListView.swift b/apps/ios/Shared/Views/ChatList/ChatListView.swift index 1d86733206..22807f6182 100644 --- a/apps/ios/Shared/Views/ChatList/ChatListView.swift +++ b/apps/ios/Shared/Views/ChatList/ChatListView.swift @@ -12,8 +12,12 @@ import SimpleXChat struct ChatListView: View { @EnvironmentObject var chatModel: ChatModel @Binding var showSettings: Bool + @State private var searchMode = false + @FocusState private var searchFocussed @State private var searchText = "" - @State private var showAddChat = false + @State private var searchShowingSimplexLink = false + @State private var searchChatFilteredBySimplexLink: String? = nil + @State private var newChatMenuOption: NewChatMenuOption? = nil @State private var userPickerVisible = false @State private var showConnectDesktop = false @AppStorage(DEFAULT_SHOW_UNREAD_AND_FAVORITES) private var showUnreadAndFavorites = false @@ -62,11 +66,7 @@ struct ChatListView: View { private var chatListView: some View { VStack { - if chatModel.chats.count > 0 { - chatList.searchable(text: $searchText) - } else { - chatList - } + chatList } .onDisappear() { withAnimation { userPickerVisible = false } } .refreshable { @@ -85,9 +85,9 @@ struct ChatListView: View { secondaryButton: .cancel() )) } - .offset(x: -8) .listStyle(.plain) .navigationBarTitleDisplayMode(.inline) + .navigationBarHidden(searchMode) .toolbar { ToolbarItem(placement: .navigationBarLeading) { let user = chatModel.currentUser ?? User.sampleData @@ -124,7 +124,7 @@ struct ChatListView: View { } ToolbarItem(placement: .navigationBarTrailing) { switch chatModel.chatRunning { - case .some(true): NewChatButton(showAddChat: $showAddChat) + case .some(true): NewChatMenuButton(newChatMenuOption: $newChatMenuOption) case .some(false): chatStoppedIcon() case .none: EmptyView() } @@ -144,11 +144,25 @@ struct ChatListView: View { @ViewBuilder private var chatList: some View { let cs = filteredChats() ZStack { - List { - ForEach(cs, id: \.viewId) { chat in - ChatListNavLink(chat: chat) - .padding(.trailing, -16) - .disabled(chatModel.chatRunning != true) + VStack { + List { + if !chatModel.chats.isEmpty { + ChatListSearchBar( + searchMode: $searchMode, + searchFocussed: $searchFocussed, + searchText: $searchText, + searchShowingSimplexLink: $searchShowingSimplexLink, + searchChatFilteredBySimplexLink: $searchChatFilteredBySimplexLink + ) + .listRowSeparator(.hidden) + .frame(maxWidth: .infinity) + } + ForEach(cs, id: \.viewId) { chat in + ChatListNavLink(chat: chat) + .padding(.trailing, -16) + .disabled(chatModel.chatRunning != true || chatModel.deletedChats.contains(chat.chatInfo.id)) + } + .offset(x: -8) } } .onChange(of: chatModel.chatId) { _ in @@ -182,7 +196,7 @@ struct ChatListView: View { .padding(.trailing, 12) connectButton("Tap to start a new chat") { - showAddChat = true + newChatMenuOption = .newContact } Spacer() @@ -214,22 +228,27 @@ struct ChatListView: View { } private func filteredChats() -> [Chat] { - let s = searchText.trimmingCharacters(in: .whitespaces).localizedLowercase - return s == "" && !showUnreadAndFavorites + if let linkChatId = searchChatFilteredBySimplexLink { + return chatModel.chats.filter { $0.id == linkChatId } + } else { + let s = searchString() + return s == "" && !showUnreadAndFavorites ? chatModel.chats : chatModel.chats.filter { chat in let cInfo = chat.chatInfo switch cInfo { case let .direct(contact): return s == "" - ? filtered(chat) - : (viewNameContains(cInfo, s) || - contact.profile.displayName.localizedLowercase.contains(s) || - contact.fullName.localizedLowercase.contains(s)) + ? filtered(chat) + : (viewNameContains(cInfo, s) || + contact.profile.displayName.localizedLowercase.contains(s) || + contact.fullName.localizedLowercase.contains(s)) case let .group(gInfo): return s == "" - ? (filtered(chat) || gInfo.membership.memberStatus == .memInvited) - : viewNameContains(cInfo, s) + ? (filtered(chat) || gInfo.membership.memberStatus == .memInvited) + : viewNameContains(cInfo, s) + case .local: + return s == "" || viewNameContains(cInfo, s) case .contactRequest: return s == "" || viewNameContains(cInfo, s) case let .contactConnection(conn): @@ -238,6 +257,11 @@ struct ChatListView: View { return false } } + } + + func searchString() -> String { + searchShowingSimplexLink ? "" : searchText.trimmingCharacters(in: .whitespaces).localizedLowercase + } func filtered(_ chat: Chat) -> Bool { (chat.chatInfo.chatSettings?.favorite ?? false) || chat.chatStats.unreadCount > 0 || chat.chatStats.unreadChat @@ -249,6 +273,121 @@ struct ChatListView: View { } } +struct ChatListSearchBar: View { + @EnvironmentObject var m: ChatModel + @Binding var searchMode: Bool + @FocusState.Binding var searchFocussed: Bool + @Binding var searchText: String + @Binding var searchShowingSimplexLink: Bool + @Binding var searchChatFilteredBySimplexLink: String? + @State private var ignoreSearchTextChange = false + @State private var showScanCodeSheet = false + @State private var alert: PlanAndConnectAlert? + @State private var sheet: PlanAndConnectActionSheet? + + var body: some View { + VStack(spacing: 12) { + HStack(spacing: 12) { + HStack(spacing: 4) { + Image(systemName: "magnifyingglass") + TextField("Search or paste SimpleX link", text: $searchText) + .foregroundColor(searchShowingSimplexLink ? .secondary : .primary) + .disabled(searchShowingSimplexLink) + .focused($searchFocussed) + .frame(maxWidth: .infinity) + if !searchText.isEmpty { + Image(systemName: "xmark.circle.fill") + .onTapGesture { + searchText = "" + } + } else if !searchFocussed { + HStack(spacing: 24) { + if m.pasteboardHasStrings { + Image(systemName: "doc") + .onTapGesture { + if let str = UIPasteboard.general.string { + searchText = str + } + } + } + + Image(systemName: "qrcode") + .resizable() + .scaledToFit() + .frame(width: 20, height: 20) + .onTapGesture { + showScanCodeSheet = true + } + } + .padding(.trailing, 2) + } + } + .padding(EdgeInsets(top: 7, leading: 7, bottom: 7, trailing: 7)) + .foregroundColor(.secondary) + .background(Color(.tertiarySystemFill)) + .cornerRadius(10.0) + + if searchFocussed { + Text("Cancel") + .foregroundColor(.accentColor) + .onTapGesture { + searchText = "" + searchFocussed = false + } + } + } + Divider() + } + .sheet(isPresented: $showScanCodeSheet) { + NewChatView(selection: .connect, showQRCodeScanner: true) + .environment(\EnvironmentValues.refresh as! WritableKeyPath<EnvironmentValues, RefreshAction?>, nil) // fixes .refreshable in ChatListView affecting nested view + } + .onChange(of: searchFocussed) { sf in + withAnimation { searchMode = sf } + } + .onChange(of: searchText) { t in + if ignoreSearchTextChange { + ignoreSearchTextChange = false + } else { + if let link = strHasSingleSimplexLink(t.trimmingCharacters(in: .whitespaces)) { // if SimpleX link is pasted, show connection dialogue + searchFocussed = false + if case let .simplexLink(linkType, _, smpHosts) = link.format { + ignoreSearchTextChange = true + searchText = simplexLinkText(linkType, smpHosts) + } + searchShowingSimplexLink = true + searchChatFilteredBySimplexLink = nil + connect(link.text) + } else { + if t != "" { // if some other text is pasted, enter search mode + searchFocussed = true + } + searchShowingSimplexLink = false + searchChatFilteredBySimplexLink = nil + } + } + } + .alert(item: $alert) { a in + planAndConnectAlert(a, dismiss: true, cleanup: { searchText = "" }) + } + .actionSheet(item: $sheet) { s in + planAndConnectActionSheet(s, dismiss: true, cleanup: { searchText = "" }) + } + } + + private func connect(_ link: String) { + planAndConnect( + link, + showAlert: { alert = $0 }, + showActionSheet: { sheet = $0 }, + dismiss: false, + incognito: nil, + filterKnownContact: { searchChatFilteredBySimplexLink = $0.id }, + filterKnownGroup: { searchChatFilteredBySimplexLink = $0.id } + ) + } +} + func chatStoppedIcon() -> some View { Button { AlertManager.shared.showAlertMsg( diff --git a/apps/ios/Shared/Views/ChatList/ChatPreviewView.swift b/apps/ios/Shared/Views/ChatList/ChatPreviewView.swift index 30068114f3..186a709ce8 100644 --- a/apps/ios/Shared/Views/ChatList/ChatPreviewView.swift +++ b/apps/ios/Shared/Views/ChatList/ChatPreviewView.swift @@ -13,6 +13,7 @@ struct ChatPreviewView: View { @EnvironmentObject var chatModel: ChatModel @ObservedObject var chat: Chat @Binding var progressByTimeout: Bool + @State var deleting: Bool = false @Environment(\.colorScheme) var colorScheme var darkGreen = Color(red: 0, green: 0.5, blue: 0) @@ -55,6 +56,9 @@ struct ChatPreviewView: View { .frame(maxHeight: .infinity) } .padding(.bottom, -8) + .onChange(of: chatModel.deletedChats.contains(chat.chatInfo.id)) { contains in + deleting = contains + } } @ViewBuilder private func chatPreviewImageOverlayIcon() -> some View { @@ -87,13 +91,13 @@ struct ChatPreviewView: View { let t = Text(chat.chatInfo.chatViewName).font(.title3).fontWeight(.bold) switch chat.chatInfo { case let .direct(contact): - previewTitle(contact.verified == true ? verifiedIcon + t : t) + previewTitle(contact.verified == true ? verifiedIcon + t : t).foregroundColor(deleting ? Color.secondary : nil) case let .group(groupInfo): let v = previewTitle(t) switch (groupInfo.membership.memberStatus) { - case .memInvited: v.foregroundColor(chat.chatInfo.incognito ? .indigo : .accentColor) + case .memInvited: v.foregroundColor(deleting ? .secondary : chat.chatInfo.incognito ? .indigo : .accentColor) case .memAccepted: v.foregroundColor(.secondary) - default: v + default: if deleting { v.foregroundColor(.secondary) } else { v } } default: previewTitle(t) } @@ -130,9 +134,9 @@ struct ChatPreviewView: View { .foregroundColor(.white) .padding(.horizontal, 4) .frame(minWidth: 18, minHeight: 18) - .background(chat.chatInfo.ntfsEnabled ? Color.accentColor : Color.secondary) + .background(chat.chatInfo.ntfsEnabled || chat.chatInfo.chatType == .local ? Color.accentColor : Color.secondary) .cornerRadius(10) - } else if !chat.chatInfo.ntfsEnabled { + } else if !chat.chatInfo.ntfsEnabled && chat.chatInfo.chatType != .local { Image(systemName: "speaker.slash.fill") .foregroundColor(.secondary) } else if chat.chatInfo.chatSettings?.favorite ?? false { @@ -150,7 +154,7 @@ struct ChatPreviewView: View { let msg = draft.message return image("rectangle.and.pencil.and.ellipsis", color: .accentColor) + attachment() - + messageText(msg, parseSimpleXMarkdown(msg), nil, preview: true) + + messageText(msg, parseSimpleXMarkdown(msg), nil, preview: true, showSecrets: false) func image(_ s: String, color: Color = Color(uiColor: .tertiaryLabel)) -> Text { Text(Image(systemName: s)).foregroundColor(color) + Text(" ") @@ -169,7 +173,7 @@ struct ChatPreviewView: View { func chatItemPreview(_ cItem: ChatItem) -> Text { let itemText = cItem.meta.itemDeleted == nil ? cItem.text : NSLocalizedString("marked deleted", comment: "marked deleted chat item preview text") let itemFormattedText = cItem.meta.itemDeleted == nil ? cItem.formattedText : nil - return messageText(itemText, itemFormattedText, cItem.memberDisplayName, icon: attachment(), preview: true) + return messageText(itemText, itemFormattedText, cItem.memberDisplayName, icon: attachment(), preview: true, showSecrets: false) func attachment() -> String? { switch cItem.content.msgContent { diff --git a/apps/ios/Shared/Views/ChatList/ContactConnectionInfo.swift b/apps/ios/Shared/Views/ChatList/ContactConnectionInfo.swift index 6d2fba99c6..42e90232d6 100644 --- a/apps/ios/Shared/Views/ChatList/ContactConnectionInfo.swift +++ b/apps/ios/Shared/Views/ChatList/ContactConnectionInfo.swift @@ -164,6 +164,28 @@ struct ContactConnectionInfo: View { } } +private func shareLinkButton(_ connReqInvitation: String) -> some View { + Button { + showShareSheet(items: [simplexChatLink(connReqInvitation)]) + } label: { + settingsRow("square.and.arrow.up") { + Text("Share 1-time link") + } + } +} + +private func oneTimeLinkLearnMoreButton() -> some View { + NavigationLink { + AddContactLearnMore(showTitle: false) + .navigationTitle("One-time invitation link") + .navigationBarTitleDisplayMode(.large) + } label: { + settingsRow("info.circle") { + Text("Learn more") + } + } +} + struct ContactConnectionInfo_Previews: PreviewProvider { static var previews: some View { ContactConnectionInfo(contactConnection: PendingContactConnection.getSampleData()) diff --git a/apps/ios/Shared/Views/Database/DatabaseErrorView.swift b/apps/ios/Shared/Views/Database/DatabaseErrorView.swift index 04e377f3a5..52ded44782 100644 --- a/apps/ios/Shared/Views/Database/DatabaseErrorView.swift +++ b/apps/ios/Shared/Views/Database/DatabaseErrorView.swift @@ -149,7 +149,7 @@ struct DatabaseErrorView: View { private func runChatSync(confirmMigrations: MigrationConfirmation? = nil) { do { resetChatCtrl() - try initializeChat(start: m.v3DBMigration.startChat, dbKey: useKeychain ? nil : dbKey, confirmMigrations: confirmMigrations) + try initializeChat(start: m.v3DBMigration.startChat, confirmStart: m.v3DBMigration.startChat && AppChatState.shared.value == .stopped, dbKey: useKeychain ? nil : dbKey, confirmMigrations: confirmMigrations) if let s = m.chatDbStatus { status = s let am = AlertManager.shared diff --git a/apps/ios/Shared/Views/Database/DatabaseView.swift b/apps/ios/Shared/Views/Database/DatabaseView.swift index 72515a1fac..31b1f618e3 100644 --- a/apps/ios/Shared/Views/Database/DatabaseView.swift +++ b/apps/ios/Shared/Views/Database/DatabaseView.swift @@ -484,6 +484,7 @@ func deleteChatAsync() async throws { try await apiDeleteStorage() _ = kcDatabasePassword.remove() storeDBPassphraseGroupDefault.set(true) + deleteAppDatabaseAndFiles() } struct DatabaseView_Previews: PreviewProvider { diff --git a/apps/ios/Shared/Views/Helpers/ChatInfoImage.swift b/apps/ios/Shared/Views/Helpers/ChatInfoImage.swift index 1b344148c0..e253cdd72c 100644 --- a/apps/ios/Shared/Views/Helpers/ChatInfoImage.swift +++ b/apps/ios/Shared/Views/Helpers/ChatInfoImage.swift @@ -10,6 +10,7 @@ import SwiftUI import SimpleXChat struct ChatInfoImage: View { + @Environment(\.colorScheme) var colorScheme @ObservedObject var chat: Chat var color = Color(uiColor: .tertiarySystemGroupedBackground) @@ -18,13 +19,16 @@ struct ChatInfoImage: View { switch chat.chatInfo { case .direct: iconName = "person.crop.circle.fill" case .group: iconName = "person.2.circle.fill" + case .local: iconName = "folder.circle.fill" case .contactRequest: iconName = "person.crop.circle.fill" default: iconName = "circle.fill" } + let notesColor = colorScheme == .light ? notesChatColorLight : notesChatColorDark + let iconColor = if case .local = chat.chatInfo { notesColor } else { color } return ProfileImage( imageStr: chat.chatInfo.image, iconName: iconName, - color: color + color: iconColor ) } } diff --git a/apps/ios/Shared/Views/LocalAuth/LocalAuthView.swift b/apps/ios/Shared/Views/LocalAuth/LocalAuthView.swift index bdb5b03e8c..9691a9efd3 100644 --- a/apps/ios/Shared/Views/LocalAuth/LocalAuthView.swift +++ b/apps/ios/Shared/Views/LocalAuth/LocalAuthView.swift @@ -13,19 +13,28 @@ struct LocalAuthView: View { @EnvironmentObject var m: ChatModel var authRequest: LocalAuthRequest @State private var password = "" + @State private var allowToReact = true var body: some View { - PasscodeView(passcode: $password, title: authRequest.title ?? "Enter Passcode", reason: authRequest.reason, submitLabel: "Submit") { + PasscodeView(passcode: $password, title: authRequest.title ?? "Enter Passcode", reason: authRequest.reason, submitLabel: "Submit", + buttonsEnabled: $allowToReact) { if let sdPassword = kcSelfDestructPassword.get(), authRequest.selfDestruct && password == sdPassword { + allowToReact = false deleteStorageAndRestart(sdPassword) { r in m.laRequest = nil authRequest.completed(r) } return } - let r: LAResult = password == authRequest.password - ? .success - : .failed(authError: NSLocalizedString("Incorrect passcode", comment: "PIN entry")) + let r: LAResult + if password == authRequest.password { + if authRequest.selfDestruct && kcSelfDestructPassword.get() != nil && !m.chatInitialized { + initChatAndMigrate() + } + r = .success + } else { + r = .failed(authError: NSLocalizedString("Incorrect passcode", comment: "PIN entry")) + } m.laRequest = nil authRequest.completed(r) } cancel: { @@ -37,8 +46,27 @@ struct LocalAuthView: View { private func deleteStorageAndRestart(_ password: String, completed: @escaping (LAResult) -> Void) { Task { do { - try await stopChatAsync() - try await deleteChatAsync() + /** Waiting until [initializeChat] finishes */ + while (m.ctrlInitInProgress) { + try await Task.sleep(nanoseconds: 50_000000) + } + if m.chatRunning == true { + try await stopChatAsync() + } + if m.chatInitialized { + /** + * The following sequence can bring a user here: + * the user opened the app, entered app passcode, went to background, returned back, entered self-destruct code. + * In this case database should be closed to prevent possible situation when OS can deny database removal command + * */ + chatCloseStore() + } + deleteAppDatabaseAndFiles() + // Clear sensitive data on screen just in case app fails to hide its views while new database is created + m.chatId = nil + m.reversedChatItems = [] + m.chats = [] + m.users = [] _ = kcAppPassword.set(password) _ = kcSelfDestructPassword.remove() await NtfManager.shared.removeAllNotifications() @@ -53,7 +81,7 @@ struct LocalAuthView: View { try initializeChat(start: true) m.chatDbChanged = false AppChatState.shared.set(.active) - if m.currentUser != nil { return } + if m.currentUser != nil || !m.chatInitialized { return } var profile: Profile? = nil if let displayName = displayName, displayName != "" { profile = Profile(displayName: displayName, fullName: "") diff --git a/apps/ios/Shared/Views/LocalAuth/PasscodeView.swift b/apps/ios/Shared/Views/LocalAuth/PasscodeView.swift index c73ded2d28..9e0d7f38b5 100644 --- a/apps/ios/Shared/Views/LocalAuth/PasscodeView.swift +++ b/apps/ios/Shared/Views/LocalAuth/PasscodeView.swift @@ -14,6 +14,8 @@ struct PasscodeView: View { var reason: String? = nil var submitLabel: LocalizedStringKey var submitEnabled: ((String) -> Bool)? + @Binding var buttonsEnabled: Bool + var submit: () -> Void var cancel: () -> Void @@ -70,11 +72,11 @@ struct PasscodeView: View { @ViewBuilder private func buttonsView() -> some View { Button(action: cancel) { Label("Cancel", systemImage: "multiply") - } + }.disabled(!buttonsEnabled) Button(action: submit) { Label(submitLabel, systemImage: "checkmark") } - .disabled(submitEnabled?(passcode) == false || passcode.count < 4) + .disabled(submitEnabled?(passcode) == false || passcode.count < 4 || !buttonsEnabled) } } @@ -85,6 +87,7 @@ struct PasscodeViewView_Previews: PreviewProvider { title: "Enter Passcode", reason: "Unlock app", submitLabel: "Submit", + buttonsEnabled: Binding.constant(true), submit: {}, cancel: {} ) diff --git a/apps/ios/Shared/Views/LocalAuth/SetAppPasscodeView.swift b/apps/ios/Shared/Views/LocalAuth/SetAppPasscodeView.swift index 76cd3e279a..7ec3ee1a42 100644 --- a/apps/ios/Shared/Views/LocalAuth/SetAppPasscodeView.swift +++ b/apps/ios/Shared/Views/LocalAuth/SetAppPasscodeView.swift @@ -11,6 +11,7 @@ import SimpleXChat struct SetAppPasscodeView: View { var passcodeKeychain: KeyChainItem = kcAppPassword + var prohibitedPasscodeKeychain: KeyChainItem = kcSelfDestructPassword var title: LocalizedStringKey = "New Passcode" var reason: String? var submit: () -> Void @@ -41,7 +42,10 @@ struct SetAppPasscodeView: View { } } } else { - setPasswordView(title: title, submitLabel: "Save") { + setPasswordView(title: title, + submitLabel: "Save", + // Do not allow to set app passcode == selfDestruct passcode + submitEnabled: { pwd in pwd != prohibitedPasscodeKeychain.get() }) { enteredPassword = passcode passcode = "" confirming = true @@ -54,7 +58,7 @@ struct SetAppPasscodeView: View { } private func setPasswordView(title: LocalizedStringKey, submitLabel: LocalizedStringKey, submitEnabled: (((String) -> Bool))? = nil, submit: @escaping () -> Void) -> some View { - PasscodeView(passcode: $passcode, title: title, reason: reason, submitLabel: submitLabel, submitEnabled: submitEnabled, submit: submit) { + PasscodeView(passcode: $passcode, title: title, reason: reason, submitLabel: submitLabel, submitEnabled: submitEnabled, buttonsEnabled: Binding.constant(true), submit: submit) { dismiss() cancel() } diff --git a/apps/ios/Shared/Views/NewChat/AddContactLearnMore.swift b/apps/ios/Shared/Views/NewChat/AddContactLearnMore.swift index 182149cbde..45eb783326 100644 --- a/apps/ios/Shared/Views/NewChat/AddContactLearnMore.swift +++ b/apps/ios/Shared/Views/NewChat/AddContactLearnMore.swift @@ -9,8 +9,20 @@ import SwiftUI struct AddContactLearnMore: View { + var showTitle: Bool + var body: some View { List { + if showTitle { + Text("One-time invitation link") + .font(.largeTitle) + .bold() + .fixedSize(horizontal: false, vertical: true) + .padding(.vertical) + .listRowBackground(Color.clear) + .listRowSeparator(.hidden) + .listRowInsets(EdgeInsets(top: 0, leading: 0, bottom: 0, trailing: 0)) + } VStack(alignment: .leading, spacing: 18) { Text("To connect, your contact can scan QR code or use the link in the app.") Text("If you can't meet in person, show QR code in a video call, or share the link.") @@ -23,6 +35,6 @@ struct AddContactLearnMore: View { struct AddContactLearnMore_Previews: PreviewProvider { static var previews: some View { - AddContactLearnMore() + AddContactLearnMore(showTitle: true) } } diff --git a/apps/ios/Shared/Views/NewChat/AddContactView.swift b/apps/ios/Shared/Views/NewChat/AddContactView.swift deleted file mode 100644 index de8e35d2a6..0000000000 --- a/apps/ios/Shared/Views/NewChat/AddContactView.swift +++ /dev/null @@ -1,129 +0,0 @@ -// -// AddContactView.swift -// SimpleX -// -// Created by Evgeny Poberezkin on 29/01/2022. -// Copyright © 2022 SimpleX Chat. All rights reserved. -// - -import SwiftUI -import CoreImage.CIFilterBuiltins -import SimpleXChat - -struct AddContactView: View { - @EnvironmentObject private var chatModel: ChatModel - @Binding var contactConnection: PendingContactConnection? - var connReqInvitation: String - @AppStorage(GROUP_DEFAULT_INCOGNITO, store: groupDefaults) private var incognitoDefault = false - - var body: some View { - VStack { - List { - Section { - if connReqInvitation != "" { - SimpleXLinkQRCode(uri: connReqInvitation) - } else { - ProgressView() - .progressViewStyle(.circular) - .scaleEffect(2) - .frame(maxWidth: .infinity) - .padding(.vertical) - } - IncognitoToggle(incognitoEnabled: $incognitoDefault) - .disabled(contactConnection == nil) - shareLinkButton(connReqInvitation) - oneTimeLinkLearnMoreButton() - } header: { - Text("1-time link") - } footer: { - sharedProfileInfo(incognitoDefault) - } - } - } - .onAppear { chatModel.connReqInv = connReqInvitation } - .onChange(of: incognitoDefault) { incognito in - Task { - do { - if let contactConn = contactConnection, - let conn = try await apiSetConnectionIncognito(connId: contactConn.pccConnId, incognito: incognito) { - await MainActor.run { - contactConnection = conn - chatModel.updateContactConnection(conn) - } - } - } catch { - logger.error("apiSetConnectionIncognito error: \(responseError(error))") - } - } - } - } -} - -struct IncognitoToggle: View { - @Binding var incognitoEnabled: Bool - @State private var showIncognitoSheet = false - - var body: some View { - ZStack(alignment: .leading) { - Image(systemName: incognitoEnabled ? "theatermasks.fill" : "theatermasks") - .frame(maxWidth: 24, maxHeight: 24, alignment: .center) - .foregroundColor(incognitoEnabled ? Color.indigo : .secondary) - .font(.system(size: 14)) - Toggle(isOn: $incognitoEnabled) { - HStack(spacing: 6) { - Text("Incognito") - Image(systemName: "info.circle") - .foregroundColor(.accentColor) - .font(.system(size: 14)) - } - .onTapGesture { - showIncognitoSheet = true - } - } - .padding(.leading, 36) - } - .sheet(isPresented: $showIncognitoSheet) { - IncognitoHelp() - } - } -} - -func sharedProfileInfo(_ incognito: Bool) -> Text { - let name = ChatModel.shared.currentUser?.displayName ?? "" - return Text( - incognito - ? "A new random profile will be shared." - : "Your profile **\(name)** will be shared." - ) -} - -func shareLinkButton(_ connReqInvitation: String) -> some View { - Button { - showShareSheet(items: [simplexChatLink(connReqInvitation)]) - } label: { - settingsRow("square.and.arrow.up") { - Text("Share 1-time link") - } - } -} - -func oneTimeLinkLearnMoreButton() -> some View { - NavigationLink { - AddContactLearnMore() - .navigationTitle("One-time invitation link") - .navigationBarTitleDisplayMode(.large) - } label: { - settingsRow("info.circle") { - Text("Learn more") - } - } -} - -struct AddContactView_Previews: PreviewProvider { - static var previews: some View { - AddContactView( - contactConnection: Binding.constant(PendingContactConnection.getSampleData()), - connReqInvitation: "https://simplex.chat/invitation#/?v=1&smp=smp%3A%2F%2Fu2dS9sG8nMNURyZwqASV4yROM28Er0luVTx5X1CsMrU%3D%40smp4.simplex.im%2FFe5ICmvrm4wkrr6X1LTMii-lhBqLeB76%23MCowBQYDK2VuAyEAdhZZsHpuaAk3Hh1q0uNb_6hGTpuwBIrsp2z9U2T0oC0%3D&e2e=v%3D1%26x3dh%3DMEIwBQYDK2VvAzkAcz6jJk71InuxA0bOX7OUhddfB8Ov7xwQIlIDeXBRZaOntUU4brU5Y3rBzroZBdQJi0FKdtt_D7I%3D%2CMEIwBQYDK2VvAzkA-hDvk1duBi1hlOr08VWSI-Ou4JNNSQjseY69QyKm7Kgg1zZjbpGfyBqSZ2eqys6xtoV4ZtoQUXQ%3D" - ) - } -} diff --git a/apps/ios/Shared/Views/NewChat/AddGroupView.swift b/apps/ios/Shared/Views/NewChat/AddGroupView.swift index 6c7919669b..3f3623033e 100644 --- a/apps/ios/Shared/Views/NewChat/AddGroupView.swift +++ b/apps/ios/Shared/Views/NewChat/AddGroupView.swift @@ -187,6 +187,7 @@ struct AddGroupView: View { hideKeyboard() do { profile.displayName = profile.displayName.trimmingCharacters(in: .whitespaces) + profile.groupPreferences = GroupPreferences(history: GroupPreference(enable: .on)) let gInfo = try apiNewGroup(incognito: incognitoDefault, groupProfile: profile) Task { let groupMembers = await apiListMembers(gInfo.groupId) diff --git a/apps/ios/Shared/Views/NewChat/ConnectViaLinkView.swift b/apps/ios/Shared/Views/NewChat/ConnectViaLinkView.swift deleted file mode 100644 index 9df767485e..0000000000 --- a/apps/ios/Shared/Views/NewChat/ConnectViaLinkView.swift +++ /dev/null @@ -1,42 +0,0 @@ -// -// ConnectViaLinkView.swift -// SimpleX (iOS) -// -// Created by Evgeny on 21/09/2022. -// Copyright © 2022 SimpleX Chat. All rights reserved. -// - -import SwiftUI - -enum ConnectViaLinkTab: String { - case scan - case paste -} - -struct ConnectViaLinkView: View { - @State private var selection: ConnectViaLinkTab = connectViaLinkTabDefault.get() - - var body: some View { - TabView(selection: $selection) { - ScanToConnectView() - .tabItem { - Label("Scan QR code", systemImage: "qrcode") - } - .tag(ConnectViaLinkTab.scan) - PasteToConnectView() - .tabItem { - Label("Paste received link", systemImage: "doc.plaintext") - } - .tag(ConnectViaLinkTab.paste) - } - .onChange(of: selection) { _ in - connectViaLinkTabDefault.set(selection) - } - } -} - -struct ConnectViaLinkView_Previews: PreviewProvider { - static var previews: some View { - ConnectViaLinkView() - } -} diff --git a/apps/ios/Shared/Views/NewChat/CreateLinkView.swift b/apps/ios/Shared/Views/NewChat/CreateLinkView.swift deleted file mode 100644 index 3be9e1c3b3..0000000000 --- a/apps/ios/Shared/Views/NewChat/CreateLinkView.swift +++ /dev/null @@ -1,94 +0,0 @@ -// -// CreateLinkView.swift -// SimpleX (iOS) -// -// Created by Evgeny on 21/09/2022. -// Copyright © 2022 SimpleX Chat. All rights reserved. -// - -import SwiftUI -import SimpleXChat - -enum CreateLinkTab { - case oneTime - case longTerm - - var title: LocalizedStringKey { - switch self { - case .oneTime: return "One-time invitation link" - case .longTerm: return "Your SimpleX address" - } - } -} - -struct CreateLinkView: View { - @EnvironmentObject var m: ChatModel - @State var selection: CreateLinkTab - @State var connReqInvitation: String = "" - @State var contactConnection: PendingContactConnection? = nil - @State private var creatingConnReq = false - var viaNavLink = false - - var body: some View { - if viaNavLink { - createLinkView() - } else { - NavigationView { - createLinkView() - } - } - } - - private func createLinkView() -> some View { - TabView(selection: $selection) { - AddContactView(contactConnection: $contactConnection, connReqInvitation: connReqInvitation) - .tabItem { - Label( - connReqInvitation == "" - ? "Create one-time invitation link" - : "One-time invitation link", - systemImage: "1.circle" - ) - } - .tag(CreateLinkTab.oneTime) - UserAddressView(viaCreateLinkView: true) - .tabItem { - Label("Your SimpleX address", systemImage: "infinity.circle") - } - .tag(CreateLinkTab.longTerm) - } - .onChange(of: selection) { _ in - if case .oneTime = selection, connReqInvitation == "", contactConnection == nil && !creatingConnReq { - createInvitation() - } - } - .onAppear { m.connReqInv = connReqInvitation } - .onDisappear { m.connReqInv = nil } - .navigationTitle(selection.title) - .navigationBarTitleDisplayMode(.large) - } - - private func createInvitation() { - creatingConnReq = true - Task { - if let (connReq, pcc) = await apiAddContact(incognito: incognitoGroupDefault.get()) { - await MainActor.run { - m.updateContactConnection(pcc) - connReqInvitation = connReq - contactConnection = pcc - m.connReqInv = connReq - } - } else { - await MainActor.run { - creatingConnReq = false - } - } - } - } -} - -struct CreateLinkView_Previews: PreviewProvider { - static var previews: some View { - CreateLinkView(selection: CreateLinkTab.oneTime) - } -} diff --git a/apps/ios/Shared/Views/NewChat/NewChatButton.swift b/apps/ios/Shared/Views/NewChat/NewChatButton.swift deleted file mode 100644 index 170805b488..0000000000 --- a/apps/ios/Shared/Views/NewChat/NewChatButton.swift +++ /dev/null @@ -1,466 +0,0 @@ -// -// NewChatButton.swift -// SimpleX -// -// Created by Evgeny Poberezkin on 31/01/2022. -// Copyright © 2022 SimpleX Chat. All rights reserved. -// - -import SwiftUI -import SimpleXChat - -enum NewChatAction: Identifiable { - case createLink(link: String, connection: PendingContactConnection) - case connectViaLink - case createGroup - - var id: String { - switch self { - case let .createLink(link, _): return "createLink \(link)" - case .connectViaLink: return "connectViaLink" - case .createGroup: return "createGroup" - } - } -} - -struct NewChatButton: View { - @Binding var showAddChat: Bool - @State private var actionSheet: NewChatAction? - - var body: some View { - Button { showAddChat = true } label: { - Image(systemName: "square.and.pencil") - .resizable() - .scaledToFit() - .frame(width: 24, height: 24) - } - .confirmationDialog("Start a new chat", isPresented: $showAddChat, titleVisibility: .visible) { - Button("Share one-time invitation link") { addContactAction() } - Button("Connect via link / QR code") { actionSheet = .connectViaLink } - Button("Create secret group") { actionSheet = .createGroup } - } - .sheet(item: $actionSheet) { sheet in - switch sheet { - case let .createLink(link, pcc): - CreateLinkView(selection: .oneTime, connReqInvitation: link, contactConnection: pcc) - case .connectViaLink: ConnectViaLinkView() - case .createGroup: AddGroupView() - } - } - } - - func addContactAction() { - Task { - if let (connReq, pcc) = await apiAddContact(incognito: incognitoGroupDefault.get()) { - await MainActor.run { - ChatModel.shared.updateContactConnection(pcc) - } - actionSheet = .createLink(link: connReq, connection: pcc) - } - } - } -} - -enum PlanAndConnectAlert: Identifiable { - case ownInvitationLinkConfirmConnect(connectionLink: String, connectionPlan: ConnectionPlan, incognito: Bool) - case invitationLinkConnecting(connectionLink: String) - case ownContactAddressConfirmConnect(connectionLink: String, connectionPlan: ConnectionPlan, incognito: Bool) - case contactAddressConnectingConfirmReconnect(connectionLink: String, connectionPlan: ConnectionPlan, incognito: Bool) - case groupLinkConfirmConnect(connectionLink: String, connectionPlan: ConnectionPlan, incognito: Bool) - case groupLinkConnectingConfirmReconnect(connectionLink: String, connectionPlan: ConnectionPlan, incognito: Bool) - case groupLinkConnecting(connectionLink: String, groupInfo: GroupInfo?) - - var id: String { - switch self { - case let .ownInvitationLinkConfirmConnect(connectionLink, _, _): return "ownInvitationLinkConfirmConnect \(connectionLink)" - case let .invitationLinkConnecting(connectionLink): return "invitationLinkConnecting \(connectionLink)" - case let .ownContactAddressConfirmConnect(connectionLink, _, _): return "ownContactAddressConfirmConnect \(connectionLink)" - case let .contactAddressConnectingConfirmReconnect(connectionLink, _, _): return "contactAddressConnectingConfirmReconnect \(connectionLink)" - case let .groupLinkConfirmConnect(connectionLink, _, _): return "groupLinkConfirmConnect \(connectionLink)" - case let .groupLinkConnectingConfirmReconnect(connectionLink, _, _): return "groupLinkConnectingConfirmReconnect \(connectionLink)" - case let .groupLinkConnecting(connectionLink, _): return "groupLinkConnecting \(connectionLink)" - } - } -} - -func planAndConnectAlert(_ alert: PlanAndConnectAlert, dismiss: Bool) -> Alert { - switch alert { - case let .ownInvitationLinkConfirmConnect(connectionLink, connectionPlan, incognito): - return Alert( - title: Text("Connect to yourself?"), - message: Text("This is your own one-time link!"), - primaryButton: .destructive( - Text(incognito ? "Connect incognito" : "Connect"), - action: { connectViaLink(connectionLink, connectionPlan: connectionPlan, dismiss: dismiss, incognito: incognito) } - ), - secondaryButton: .cancel() - ) - case .invitationLinkConnecting: - return Alert( - title: Text("Already connecting!"), - message: Text("You are already connecting via this one-time link!") - ) - case let .ownContactAddressConfirmConnect(connectionLink, connectionPlan, incognito): - return Alert( - title: Text("Connect to yourself?"), - message: Text("This is your own SimpleX address!"), - primaryButton: .destructive( - Text(incognito ? "Connect incognito" : "Connect"), - action: { connectViaLink(connectionLink, connectionPlan: connectionPlan, dismiss: dismiss, incognito: incognito) } - ), - secondaryButton: .cancel() - ) - case let .contactAddressConnectingConfirmReconnect(connectionLink, connectionPlan, incognito): - return Alert( - title: Text("Repeat connection request?"), - message: Text("You have already requested connection via this address!"), - primaryButton: .destructive( - Text(incognito ? "Connect incognito" : "Connect"), - action: { connectViaLink(connectionLink, connectionPlan: connectionPlan, dismiss: dismiss, incognito: incognito) } - ), - secondaryButton: .cancel() - ) - case let .groupLinkConfirmConnect(connectionLink, connectionPlan, incognito): - return Alert( - title: Text("Join group?"), - message: Text("You will connect to all group members."), - primaryButton: .default( - Text(incognito ? "Join incognito" : "Join"), - action: { connectViaLink(connectionLink, connectionPlan: connectionPlan, dismiss: dismiss, incognito: incognito) } - ), - secondaryButton: .cancel() - ) - case let .groupLinkConnectingConfirmReconnect(connectionLink, connectionPlan, incognito): - return Alert( - title: Text("Repeat join request?"), - message: Text("You are already joining the group via this link!"), - primaryButton: .destructive( - Text(incognito ? "Join incognito" : "Join"), - action: { connectViaLink(connectionLink, connectionPlan: connectionPlan, dismiss: dismiss, incognito: incognito) } - ), - secondaryButton: .cancel() - ) - case let .groupLinkConnecting(_, groupInfo): - if let groupInfo = groupInfo { - return Alert( - title: Text("Group already exists!"), - message: Text("You are already joining the group \(groupInfo.displayName).") - ) - } else { - return Alert( - title: Text("Already joining the group!"), - message: Text("You are already joining the group via this link.") - ) - } - } -} - -enum PlanAndConnectActionSheet: Identifiable { - case askCurrentOrIncognitoProfile(connectionLink: String, connectionPlan: ConnectionPlan?, title: LocalizedStringKey) - case askCurrentOrIncognitoProfileDestructive(connectionLink: String, connectionPlan: ConnectionPlan, title: LocalizedStringKey) - case askCurrentOrIncognitoProfileConnectContactViaAddress(contact: Contact) - case ownGroupLinkConfirmConnect(connectionLink: String, connectionPlan: ConnectionPlan, incognito: Bool?, groupInfo: GroupInfo) - - var id: String { - switch self { - case let .askCurrentOrIncognitoProfile(connectionLink, _, _): return "askCurrentOrIncognitoProfile \(connectionLink)" - case let .askCurrentOrIncognitoProfileDestructive(connectionLink, _, _): return "askCurrentOrIncognitoProfileDestructive \(connectionLink)" - case let .askCurrentOrIncognitoProfileConnectContactViaAddress(contact): return "askCurrentOrIncognitoProfileConnectContactViaAddress \(contact.contactId)" - case let .ownGroupLinkConfirmConnect(connectionLink, _, _, _): return "ownGroupLinkConfirmConnect \(connectionLink)" - } - } -} - -func planAndConnectActionSheet(_ sheet: PlanAndConnectActionSheet, dismiss: Bool) -> ActionSheet { - switch sheet { - case let .askCurrentOrIncognitoProfile(connectionLink, connectionPlan, title): - return ActionSheet( - title: Text(title), - buttons: [ - .default(Text("Use current profile")) { connectViaLink(connectionLink, connectionPlan: connectionPlan, dismiss: dismiss, incognito: false) }, - .default(Text("Use new incognito profile")) { connectViaLink(connectionLink, connectionPlan: connectionPlan, dismiss: dismiss, incognito: true) }, - .cancel() - ] - ) - case let .askCurrentOrIncognitoProfileDestructive(connectionLink, connectionPlan, title): - return ActionSheet( - title: Text(title), - buttons: [ - .destructive(Text("Use current profile")) { connectViaLink(connectionLink, connectionPlan: connectionPlan, dismiss: dismiss, incognito: false) }, - .destructive(Text("Use new incognito profile")) { connectViaLink(connectionLink, connectionPlan: connectionPlan, dismiss: dismiss, incognito: true) }, - .cancel() - ] - ) - case let .askCurrentOrIncognitoProfileConnectContactViaAddress(contact): - return ActionSheet( - title: Text("Connect with \(contact.chatViewName)"), - buttons: [ - .default(Text("Use current profile")) { connectContactViaAddress_(contact, dismiss: dismiss, incognito: false) }, - .default(Text("Use new incognito profile")) { connectContactViaAddress_(contact, dismiss: dismiss, incognito: true) }, - .cancel() - ] - ) - case let .ownGroupLinkConfirmConnect(connectionLink, connectionPlan, incognito, groupInfo): - if let incognito = incognito { - return ActionSheet( - title: Text("Join your group?\nThis is your link for group \(groupInfo.displayName)!"), - buttons: [ - .default(Text("Open group")) { openKnownGroup(groupInfo, dismiss: dismiss, showAlreadyExistsAlert: nil) }, - .destructive(Text(incognito ? "Join incognito" : "Join with current profile")) { connectViaLink(connectionLink, connectionPlan: connectionPlan, dismiss: dismiss, incognito: incognito) }, - .cancel() - ] - ) - } else { - return ActionSheet( - title: Text("Join your group?\nThis is your link for group \(groupInfo.displayName)!"), - buttons: [ - .default(Text("Open group")) { openKnownGroup(groupInfo, dismiss: dismiss, showAlreadyExistsAlert: nil) }, - .destructive(Text("Use current profile")) { connectViaLink(connectionLink, connectionPlan: connectionPlan, dismiss: dismiss, incognito: false) }, - .destructive(Text("Use new incognito profile")) { connectViaLink(connectionLink, connectionPlan: connectionPlan, dismiss: dismiss, incognito: true) }, - .cancel() - ] - ) - } - } -} - -func planAndConnect( - _ connectionLink: String, - showAlert: @escaping (PlanAndConnectAlert) -> Void, - showActionSheet: @escaping (PlanAndConnectActionSheet) -> Void, - dismiss: Bool, - incognito: Bool? -) { - Task { - do { - let connectionPlan = try await apiConnectPlan(connReq: connectionLink) - switch connectionPlan { - case let .invitationLink(ilp): - switch ilp { - case .ok: - logger.debug("planAndConnect, .invitationLink, .ok, incognito=\(incognito?.description ?? "nil")") - if let incognito = incognito { - connectViaLink(connectionLink, connectionPlan: connectionPlan, dismiss: dismiss, incognito: incognito) - } else { - showActionSheet(.askCurrentOrIncognitoProfile(connectionLink: connectionLink, connectionPlan: connectionPlan, title: "Connect via one-time link")) - } - case .ownLink: - logger.debug("planAndConnect, .invitationLink, .ownLink, incognito=\(incognito?.description ?? "nil")") - if let incognito = incognito { - showAlert(.ownInvitationLinkConfirmConnect(connectionLink: connectionLink, connectionPlan: connectionPlan, incognito: incognito)) - } else { - showActionSheet(.askCurrentOrIncognitoProfileDestructive(connectionLink: connectionLink, connectionPlan: connectionPlan, title: "Connect to yourself?\nThis is your own one-time link!")) - } - case let .connecting(contact_): - logger.debug("planAndConnect, .invitationLink, .connecting, incognito=\(incognito?.description ?? "nil")") - if let contact = contact_ { - openKnownContact(contact, dismiss: dismiss) { AlertManager.shared.showAlert(contactAlreadyConnectingAlert(contact)) } - } else { - showAlert(.invitationLinkConnecting(connectionLink: connectionLink)) - } - case let .known(contact): - logger.debug("planAndConnect, .invitationLink, .known, incognito=\(incognito?.description ?? "nil")") - openKnownContact(contact, dismiss: dismiss) { AlertManager.shared.showAlert(contactAlreadyExistsAlert(contact)) } - } - case let .contactAddress(cap): - switch cap { - case .ok: - logger.debug("planAndConnect, .contactAddress, .ok, incognito=\(incognito?.description ?? "nil")") - if let incognito = incognito { - connectViaLink(connectionLink, connectionPlan: connectionPlan, dismiss: dismiss, incognito: incognito) - } else { - showActionSheet(.askCurrentOrIncognitoProfile(connectionLink: connectionLink, connectionPlan: connectionPlan, title: "Connect via contact address")) - } - case .ownLink: - logger.debug("planAndConnect, .contactAddress, .ownLink, incognito=\(incognito?.description ?? "nil")") - if let incognito = incognito { - showAlert(.ownContactAddressConfirmConnect(connectionLink: connectionLink, connectionPlan: connectionPlan, incognito: incognito)) - } else { - showActionSheet(.askCurrentOrIncognitoProfileDestructive(connectionLink: connectionLink, connectionPlan: connectionPlan, title: "Connect to yourself?\nThis is your own SimpleX address!")) - } - case .connectingConfirmReconnect: - logger.debug("planAndConnect, .contactAddress, .connectingConfirmReconnect, incognito=\(incognito?.description ?? "nil")") - if let incognito = incognito { - showAlert(.contactAddressConnectingConfirmReconnect(connectionLink: connectionLink, connectionPlan: connectionPlan, incognito: incognito)) - } else { - showActionSheet(.askCurrentOrIncognitoProfileDestructive(connectionLink: connectionLink, connectionPlan: connectionPlan, title: "You have already requested connection!\nRepeat connection request?")) - } - case let .connectingProhibit(contact): - logger.debug("planAndConnect, .contactAddress, .connectingProhibit, incognito=\(incognito?.description ?? "nil")") - openKnownContact(contact, dismiss: dismiss) { AlertManager.shared.showAlert(contactAlreadyConnectingAlert(contact)) } - case let .known(contact): - logger.debug("planAndConnect, .contactAddress, .known, incognito=\(incognito?.description ?? "nil")") - openKnownContact(contact, dismiss: dismiss) { AlertManager.shared.showAlert(contactAlreadyExistsAlert(contact)) } - case let .contactViaAddress(contact): - logger.debug("planAndConnect, .contactAddress, .contactViaAddress, incognito=\(incognito?.description ?? "nil")") - if let incognito = incognito { - connectContactViaAddress_(contact, dismiss: dismiss, incognito: incognito) - } else { - showActionSheet(.askCurrentOrIncognitoProfileConnectContactViaAddress(contact: contact)) - } - } - case let .groupLink(glp): - switch glp { - case .ok: - if let incognito = incognito { - showAlert(.groupLinkConfirmConnect(connectionLink: connectionLink, connectionPlan: connectionPlan, incognito: incognito)) - } else { - showActionSheet(.askCurrentOrIncognitoProfile(connectionLink: connectionLink, connectionPlan: connectionPlan, title: "Join group")) - } - case let .ownLink(groupInfo): - logger.debug("planAndConnect, .groupLink, .ownLink, incognito=\(incognito?.description ?? "nil")") - showActionSheet(.ownGroupLinkConfirmConnect(connectionLink: connectionLink, connectionPlan: connectionPlan, incognito: incognito, groupInfo: groupInfo)) - case .connectingConfirmReconnect: - logger.debug("planAndConnect, .groupLink, .connectingConfirmReconnect, incognito=\(incognito?.description ?? "nil")") - if let incognito = incognito { - showAlert(.groupLinkConnectingConfirmReconnect(connectionLink: connectionLink, connectionPlan: connectionPlan, incognito: incognito)) - } else { - showActionSheet(.askCurrentOrIncognitoProfileDestructive(connectionLink: connectionLink, connectionPlan: connectionPlan, title: "You are already joining the group!\nRepeat join request?")) - } - case let .connectingProhibit(groupInfo_): - logger.debug("planAndConnect, .groupLink, .connectingProhibit, incognito=\(incognito?.description ?? "nil")") - showAlert(.groupLinkConnecting(connectionLink: connectionLink, groupInfo: groupInfo_)) - case let .known(groupInfo): - logger.debug("planAndConnect, .groupLink, .known, incognito=\(incognito?.description ?? "nil")") - openKnownGroup(groupInfo, dismiss: dismiss) { AlertManager.shared.showAlert(groupAlreadyExistsAlert(groupInfo)) } - } - } - } catch { - logger.debug("planAndConnect, plan error") - if let incognito = incognito { - connectViaLink(connectionLink, connectionPlan: nil, dismiss: dismiss, incognito: incognito) - } else { - showActionSheet(.askCurrentOrIncognitoProfile(connectionLink: connectionLink, connectionPlan: nil, title: "Connect via link")) - } - } - } -} - -private func connectContactViaAddress_(_ contact: Contact, dismiss: Bool, incognito: Bool) { - Task { - if dismiss { - DispatchQueue.main.async { - dismissAllSheets(animated: true) - } - } - _ = await connectContactViaAddress(contact.contactId, incognito) - } -} - -private func connectViaLink(_ connectionLink: String, connectionPlan: ConnectionPlan?, dismiss: Bool, incognito: Bool) { - Task { - if let (connReqType, pcc) = await apiConnect(incognito: incognito, connReq: connectionLink) { - await MainActor.run { - ChatModel.shared.updateContactConnection(pcc) - } - let crt: ConnReqType - if let plan = connectionPlan { - crt = planToConnReqType(plan) - } else { - crt = connReqType - } - DispatchQueue.main.async { - if dismiss { - dismissAllSheets(animated: true) { - AlertManager.shared.showAlert(connReqSentAlert(crt)) - } - } else { - AlertManager.shared.showAlert(connReqSentAlert(crt)) - } - } - } else { - if dismiss { - DispatchQueue.main.async { - dismissAllSheets(animated: true) - } - } - } - } -} - -func openKnownContact(_ contact: Contact, dismiss: Bool, showAlreadyExistsAlert: (() -> Void)?) { - Task { - let m = ChatModel.shared - if let c = m.getContactChat(contact.contactId) { - DispatchQueue.main.async { - if dismiss { - dismissAllSheets(animated: true) { - m.chatId = c.id - showAlreadyExistsAlert?() - } - } else { - m.chatId = c.id - showAlreadyExistsAlert?() - } - } - } - } -} - -func openKnownGroup(_ groupInfo: GroupInfo, dismiss: Bool, showAlreadyExistsAlert: (() -> Void)?) { - Task { - let m = ChatModel.shared - if let g = m.getGroupChat(groupInfo.groupId) { - DispatchQueue.main.async { - if dismiss { - dismissAllSheets(animated: true) { - m.chatId = g.id - showAlreadyExistsAlert?() - } - } else { - m.chatId = g.id - showAlreadyExistsAlert?() - } - } - } - } -} - -func contactAlreadyConnectingAlert(_ contact: Contact) -> Alert { - mkAlert( - title: "Contact already exists", - message: "You are already connecting to \(contact.displayName)." - ) -} - -func groupAlreadyExistsAlert(_ groupInfo: GroupInfo) -> Alert { - mkAlert( - title: "Group already exists", - message: "You are already in group \(groupInfo.displayName)." - ) -} - -enum ConnReqType: Equatable { - case invitation - case contact - case groupLink - - var connReqSentText: LocalizedStringKey { - switch self { - case .invitation: return "You will be connected when your contact's device is online, please wait or check later!" - case .contact: return "You will be connected when your connection request is accepted, please wait or check later!" - case .groupLink: return "You will be connected when group link host's device is online, please wait or check later!" - } - } -} - -private func planToConnReqType(_ connectionPlan: ConnectionPlan) -> ConnReqType { - switch connectionPlan { - case .invitationLink: return .invitation - case .contactAddress: return .contact - case .groupLink: return .groupLink - } -} - -func connReqSentAlert(_ type: ConnReqType) -> Alert { - return mkAlert( - title: "Connection request sent!", - message: type.connReqSentText - ) -} - -struct NewChatButton_Previews: PreviewProvider { - static var previews: some View { - NewChatButton(showAddChat: Binding.constant(false)) - } -} diff --git a/apps/ios/Shared/Views/NewChat/NewChatMenuButton.swift b/apps/ios/Shared/Views/NewChat/NewChatMenuButton.swift new file mode 100644 index 0000000000..c3452ce18d --- /dev/null +++ b/apps/ios/Shared/Views/NewChat/NewChatMenuButton.swift @@ -0,0 +1,52 @@ +// +// NewChatMenuButton.swift +// SimpleX (iOS) +// +// Created by spaced4ndy on 28.11.2023. +// Copyright © 2023 SimpleX Chat. All rights reserved. +// + +import SwiftUI + +enum NewChatMenuOption: Identifiable { + case newContact + case newGroup + + var id: Self { self } +} + +struct NewChatMenuButton: View { + @Binding var newChatMenuOption: NewChatMenuOption? + + var body: some View { + Menu { + Button { + newChatMenuOption = .newContact + } label: { + Text("Add contact") + } + Button { + newChatMenuOption = .newGroup + } label: { + Text("Create group") + } + } label: { + Image(systemName: "square.and.pencil") + .resizable() + .scaledToFit() + .frame(width: 24, height: 24) + } + .sheet(item: $newChatMenuOption) { opt in + switch opt { + case .newContact: NewChatView(selection: .invite) + case .newGroup: AddGroupView() + } + } + } +} + +#Preview { + NewChatMenuButton( + newChatMenuOption: Binding.constant(nil) + ) +} diff --git a/apps/ios/Shared/Views/NewChat/NewChatView.swift b/apps/ios/Shared/Views/NewChat/NewChatView.swift new file mode 100644 index 0000000000..b78d92ffc8 --- /dev/null +++ b/apps/ios/Shared/Views/NewChat/NewChatView.swift @@ -0,0 +1,959 @@ +// +// NewChatView.swift +// SimpleX (iOS) +// +// Created by spaced4ndy on 28.11.2023. +// Copyright © 2023 SimpleX Chat. All rights reserved. +// + +import SwiftUI +import SimpleXChat +import CodeScanner +import AVFoundation + +enum SomeAlert: Identifiable { + case someAlert(alert: Alert, id: String) + + var id: String { + switch self { + case let .someAlert(_, id): return id + } + } +} + +private enum NewChatViewAlert: Identifiable { + case planAndConnectAlert(alert: PlanAndConnectAlert) + case newChatSomeAlert(alert: SomeAlert) + + var id: String { + switch self { + case let .planAndConnectAlert(alert): return "planAndConnectAlert \(alert.id)" + case let .newChatSomeAlert(alert): return "newChatSomeAlert \(alert.id)" + } + } +} + +enum NewChatOption: Identifiable { + case invite + case connect + + var id: Self { self } +} + +struct NewChatView: View { + @EnvironmentObject var m: ChatModel + @State var selection: NewChatOption + @State var showQRCodeScanner = false + @State private var invitationUsed: Bool = false + @State private var contactConnection: PendingContactConnection? = nil + @State private var connReqInvitation: String = "" + @State private var creatingConnReq = false + @State private var pastedLink: String = "" + @State private var alert: NewChatViewAlert? + + var body: some View { + VStack(alignment: .leading) { + HStack { + Text("New chat") + .font(.largeTitle) + .bold() + .fixedSize(horizontal: false, vertical: true) + Spacer() + InfoSheetButton { + AddContactLearnMore(showTitle: true) + } + } + .padding() + .padding(.top) + + Picker("New chat", selection: $selection) { + Label("Add contact", systemImage: "link") + .tag(NewChatOption.invite) + Label("Connect via link", systemImage: "qrcode") + .tag(NewChatOption.connect) + } + .pickerStyle(.segmented) + .padding() + + VStack { + // it seems there's a bug in iOS 15 if several views in switch (or if-else) statement have different transitions + // https://developer.apple.com/forums/thread/714977?answerId=731615022#731615022 + if case .invite = selection { + prepareAndInviteView() + .transition(.move(edge: .leading)) + .onAppear { + createInvitation() + } + } + if case .connect = selection { + ConnectView(showQRCodeScanner: showQRCodeScanner, pastedLink: $pastedLink, alert: $alert) + .transition(.move(edge: .trailing)) + } + } + .frame(maxWidth: .infinity, maxHeight: .infinity) + .background( + // Rectangle is needed for swipe gesture to work on mostly empty views (creatingLinkProgressView and retryButton) + Rectangle() + .fill(Color(uiColor: .systemGroupedBackground)) + ) + .animation(.easeInOut(duration: 0.3333), value: selection) + .gesture(DragGesture(minimumDistance: 20.0, coordinateSpace: .local) + .onChanged { value in + switch(value.translation.width, value.translation.height) { + case (...0, -30...30): // left swipe + if selection == .invite { + selection = .connect + } + case (0..., -30...30): // right swipe + if selection == .connect { + selection = .invite + } + default: () + } + } + ) + } + .background(Color(.systemGroupedBackground)) + .onChange(of: invitationUsed) { used in + if used && !(m.showingInvitation?.connChatUsed ?? true) { + m.markShowingInvitationUsed() + } + } + .onDisappear { + if !(m.showingInvitation?.connChatUsed ?? true), + let conn = contactConnection { + AlertManager.shared.showAlert(Alert( + title: Text("Keep unused invitation?"), + message: Text("You can view invitation link again in connection details."), + primaryButton: .default(Text("Keep")) {}, + secondaryButton: .destructive(Text("Delete")) { + Task { + await deleteChat(Chat( + chatInfo: .contactConnection(contactConnection: conn), + chatItems: [] + )) + } + } + )) + } + m.showingInvitation = nil + } + .alert(item: $alert) { a in + switch(a) { + case let .planAndConnectAlert(alert): + return planAndConnectAlert(alert, dismiss: true, cleanup: { pastedLink = "" }) + case let .newChatSomeAlert(.someAlert(alert, _)): + return alert + } + } + } + + private func prepareAndInviteView() -> some View { + ZStack { // ZStack is needed for views to not make transitions between each other + if connReqInvitation != "" { + InviteView( + invitationUsed: $invitationUsed, + contactConnection: $contactConnection, + connReqInvitation: connReqInvitation + ) + } else if creatingConnReq { + creatingLinkProgressView() + } else { + retryButton() + } + } + } + + private func createInvitation() { + if connReqInvitation == "" && contactConnection == nil && !creatingConnReq { + creatingConnReq = true + Task { + _ = try? await Task.sleep(nanoseconds: 250_000000) + let (r, apiAlert) = await apiAddContact(incognito: incognitoGroupDefault.get()) + if let (connReq, pcc) = r { + await MainActor.run { + m.updateContactConnection(pcc) + m.showingInvitation = ShowingInvitation(connId: pcc.id, connChatUsed: false) + connReqInvitation = connReq + contactConnection = pcc + } + } else { + await MainActor.run { + creatingConnReq = false + if let apiAlert = apiAlert { + alert = .newChatSomeAlert(alert: .someAlert(alert: apiAlert, id: "createInvitation error")) + } + } + } + } + } + } + + // Rectangle here and in retryButton are needed for gesture to work + private func creatingLinkProgressView() -> some View { + ProgressView("Creating link…") + .progressViewStyle(.circular) + } + + private func retryButton() -> some View { + Button(action: createInvitation) { + VStack(spacing: 6) { + Image(systemName: "arrow.counterclockwise") + Text("Retry") + } + } + } +} + +private struct InviteView: View { + @EnvironmentObject var chatModel: ChatModel + @Binding var invitationUsed: Bool + @Binding var contactConnection: PendingContactConnection? + var connReqInvitation: String + @AppStorage(GROUP_DEFAULT_INCOGNITO, store: groupDefaults) private var incognitoDefault = false + + var body: some View { + List { + Section("Share this 1-time invite link") { + shareLinkView() + } + .listRowInsets(EdgeInsets(top: 0, leading: 20, bottom: 0, trailing: 10)) + + qrCodeView() + + Section { + IncognitoToggle(incognitoEnabled: $incognitoDefault) + } footer: { + sharedProfileInfo(incognitoDefault) + } + } + .onChange(of: incognitoDefault) { incognito in + Task { + do { + if let contactConn = contactConnection, + let conn = try await apiSetConnectionIncognito(connId: contactConn.pccConnId, incognito: incognito) { + await MainActor.run { + contactConnection = conn + chatModel.updateContactConnection(conn) + } + } + } catch { + logger.error("apiSetConnectionIncognito error: \(responseError(error))") + } + } + setInvitationUsed() + } + } + + private func shareLinkView() -> some View { + HStack { + let link = simplexChatLink(connReqInvitation) + linkTextView(link) + Button { + showShareSheet(items: [link]) + setInvitationUsed() + } label: { + Image(systemName: "square.and.arrow.up") + .padding(.top, -7) + } + } + .frame(maxWidth: .infinity) + } + + private func qrCodeView() -> some View { + Section("Or show this code") { + SimpleXLinkQRCode(uri: connReqInvitation, onShare: setInvitationUsed) + .padding() + .background( + RoundedRectangle(cornerRadius: 12, style: .continuous) + .fill(Color(uiColor: .secondarySystemGroupedBackground)) + ) + .padding(.horizontal) + .listRowBackground(Color.clear) + .listRowSeparator(.hidden) + .listRowInsets(EdgeInsets(top: 0, leading: 0, bottom: 0, trailing: 0)) + } + } + + private func setInvitationUsed() { + if !invitationUsed { + invitationUsed = true + } + } +} + +private struct ConnectView: View { + @Environment(\.dismiss) var dismiss: DismissAction + @State var showQRCodeScanner = false + @State private var cameraAuthorizationStatus: AVAuthorizationStatus? + @Binding var pastedLink: String + @Binding var alert: NewChatViewAlert? + @State private var sheet: PlanAndConnectActionSheet? + + var body: some View { + List { + Section("Paste the link you received") { + pasteLinkView() + } + + scanCodeView() + } + .actionSheet(item: $sheet) { s in + planAndConnectActionSheet(s, dismiss: true, cleanup: { pastedLink = "" }) + } + .onAppear { + let status = AVCaptureDevice.authorizationStatus(for: .video) + cameraAuthorizationStatus = status + if showQRCodeScanner { + switch status { + case .notDetermined: askCameraAuthorization() + case .restricted: showQRCodeScanner = false + case .denied: showQRCodeScanner = false + case .authorized: () + @unknown default: askCameraAuthorization() + } + } + } + } + + func askCameraAuthorization(_ cb: (() -> Void)? = nil) { + AVCaptureDevice.requestAccess(for: .video) { allowed in + cameraAuthorizationStatus = AVCaptureDevice.authorizationStatus(for: .video) + if allowed { cb?() } + } + } + + @ViewBuilder private func pasteLinkView() -> some View { + if pastedLink == "" { + Button { + if let str = UIPasteboard.general.string { + if let link = strHasSingleSimplexLink(str.trimmingCharacters(in: .whitespaces)) { + pastedLink = link.text + // It would be good to hide it, but right now it is not clear how to release camera in CodeScanner + // https://github.com/twostraws/CodeScanner/issues/121 + // No known tricks worked (changing view ID, wrapping it in another view, etc.) + // showQRCodeScanner = false + connect(pastedLink) + } else { + alert = .newChatSomeAlert(alert: .someAlert( + alert: mkAlert(title: "Invalid link", message: "The text you pasted is not a SimpleX link."), + id: "pasteLinkView: code is not a SimpleX link" + )) + } + } + } label: { + Text("Tap to paste link") + } + .disabled(!ChatModel.shared.pasteboardHasStrings) + .frame(maxWidth: .infinity, alignment: .center) + } else { + linkTextView(pastedLink) + } + } + + private func scanCodeView() -> some View { + Section("Or scan QR code") { + if showQRCodeScanner, case .authorized = cameraAuthorizationStatus { + CodeScannerView(codeTypes: [.qr], scanMode: .continuous, completion: processQRCode) + .aspectRatio(1, contentMode: .fit) + .cornerRadius(12) + .listRowBackground(Color.clear) + .listRowSeparator(.hidden) + .listRowInsets(EdgeInsets(top: 0, leading: 0, bottom: 0, trailing: 0)) + .padding(.horizontal) + } else { + Button { + switch cameraAuthorizationStatus { + case .notDetermined: askCameraAuthorization { showQRCodeScanner = true } + case .restricted: () + case .denied: UIApplication.shared.open(appSettingsURL) + case .authorized: showQRCodeScanner = true + default: askCameraAuthorization { showQRCodeScanner = true } + } + } label: { + ZStack { + Rectangle() + .aspectRatio(contentMode: .fill) + .frame(maxWidth: .infinity, maxHeight: .infinity) + .foregroundColor(Color.clear) + switch cameraAuthorizationStatus { + case .restricted: Text("Camera not available") + case .denied: Label("Enable camera access", systemImage: "camera") + default: Label("Tap to scan", systemImage: "qrcode") + } + } + } + .frame(maxWidth: .infinity, maxHeight: .infinity, alignment: .center) + .padding() + .background( + RoundedRectangle(cornerRadius: 12, style: .continuous) + .fill(Color(uiColor: .secondarySystemGroupedBackground)) + ) + .padding(.horizontal) + .listRowBackground(Color.clear) + .listRowSeparator(.hidden) + .listRowInsets(EdgeInsets(top: 0, leading: 0, bottom: 0, trailing: 0)) + .disabled(cameraAuthorizationStatus == .restricted) + } + } + } + + private func processQRCode(_ resp: Result<ScanResult, ScanError>) { + switch resp { + case let .success(r): + let link = r.string + if strIsSimplexLink(r.string) { + connect(link) + } else { + alert = .newChatSomeAlert(alert: .someAlert( + alert: mkAlert(title: "Invalid QR code", message: "The code you scanned is not a SimpleX link QR code."), + id: "processQRCode: code is not a SimpleX link" + )) + } + case let .failure(e): + logger.error("processQRCode QR code error: \(e.localizedDescription)") + alert = .newChatSomeAlert(alert: .someAlert( + alert: mkAlert(title: "Invalid QR code", message: "Error scanning code: \(e.localizedDescription)"), + id: "processQRCode: failure" + )) + } + } + + private func connect(_ link: String) { + planAndConnect( + link, + showAlert: { alert = .planAndConnectAlert(alert: $0) }, + showActionSheet: { sheet = $0 }, + dismiss: true, + incognito: nil + ) + } +} + +private func linkTextView(_ link: String) -> some View { + Text(link) + .lineLimit(1) + .font(.caption) + .truncationMode(.middle) +} + +struct InfoSheetButton<Content: View>: View { + @ViewBuilder let content: Content + @State private var showInfoSheet = false + + var body: some View { + Button { + showInfoSheet = true + } label: { + Image(systemName: "info.circle") + .resizable() + .scaledToFit() + .frame(width: 24, height: 24) + } + .sheet(isPresented: $showInfoSheet) { + content + } + } +} + +func strIsSimplexLink(_ str: String) -> Bool { + if let parsedMd = parseSimpleXMarkdown(str), + parsedMd.count == 1, + case .simplexLink = parsedMd[0].format { + return true + } else { + return false + } +} + +func strHasSingleSimplexLink(_ str: String) -> FormattedText? { + if let parsedMd = parseSimpleXMarkdown(str) { + let parsedLinks = parsedMd.filter({ $0.format?.isSimplexLink ?? false }) + if parsedLinks.count == 1 { + return parsedLinks[0] + } else { + return nil + } + } else { + return nil + } +} + +struct IncognitoToggle: View { + @Binding var incognitoEnabled: Bool + @State private var showIncognitoSheet = false + + var body: some View { + ZStack(alignment: .leading) { + Image(systemName: incognitoEnabled ? "theatermasks.fill" : "theatermasks") + .frame(maxWidth: 24, maxHeight: 24, alignment: .center) + .foregroundColor(incognitoEnabled ? Color.indigo : .secondary) + .font(.system(size: 14)) + Toggle(isOn: $incognitoEnabled) { + HStack(spacing: 6) { + Text("Incognito") + Image(systemName: "info.circle") + .foregroundColor(.accentColor) + .font(.system(size: 14)) + } + .onTapGesture { + showIncognitoSheet = true + } + } + .padding(.leading, 36) + } + .sheet(isPresented: $showIncognitoSheet) { + IncognitoHelp() + } + } +} + +func sharedProfileInfo(_ incognito: Bool) -> Text { + let name = ChatModel.shared.currentUser?.displayName ?? "" + return Text( + incognito + ? "A new random profile will be shared." + : "Your profile **\(name)** will be shared." + ) +} + +enum PlanAndConnectAlert: Identifiable { + case ownInvitationLinkConfirmConnect(connectionLink: String, connectionPlan: ConnectionPlan, incognito: Bool) + case invitationLinkConnecting(connectionLink: String) + case ownContactAddressConfirmConnect(connectionLink: String, connectionPlan: ConnectionPlan, incognito: Bool) + case contactAddressConnectingConfirmReconnect(connectionLink: String, connectionPlan: ConnectionPlan, incognito: Bool) + case groupLinkConfirmConnect(connectionLink: String, connectionPlan: ConnectionPlan, incognito: Bool) + case groupLinkConnectingConfirmReconnect(connectionLink: String, connectionPlan: ConnectionPlan, incognito: Bool) + case groupLinkConnecting(connectionLink: String, groupInfo: GroupInfo?) + + var id: String { + switch self { + case let .ownInvitationLinkConfirmConnect(connectionLink, _, _): return "ownInvitationLinkConfirmConnect \(connectionLink)" + case let .invitationLinkConnecting(connectionLink): return "invitationLinkConnecting \(connectionLink)" + case let .ownContactAddressConfirmConnect(connectionLink, _, _): return "ownContactAddressConfirmConnect \(connectionLink)" + case let .contactAddressConnectingConfirmReconnect(connectionLink, _, _): return "contactAddressConnectingConfirmReconnect \(connectionLink)" + case let .groupLinkConfirmConnect(connectionLink, _, _): return "groupLinkConfirmConnect \(connectionLink)" + case let .groupLinkConnectingConfirmReconnect(connectionLink, _, _): return "groupLinkConnectingConfirmReconnect \(connectionLink)" + case let .groupLinkConnecting(connectionLink, _): return "groupLinkConnecting \(connectionLink)" + } + } +} + +func planAndConnectAlert(_ alert: PlanAndConnectAlert, dismiss: Bool, cleanup: (() -> Void)? = nil) -> Alert { + switch alert { + case let .ownInvitationLinkConfirmConnect(connectionLink, connectionPlan, incognito): + return Alert( + title: Text("Connect to yourself?"), + message: Text("This is your own one-time link!"), + primaryButton: .destructive( + Text(incognito ? "Connect incognito" : "Connect"), + action: { connectViaLink(connectionLink, connectionPlan: connectionPlan, dismiss: dismiss, incognito: incognito, cleanup: cleanup) } + ), + secondaryButton: .cancel() { cleanup?() } + ) + case .invitationLinkConnecting: + return Alert( + title: Text("Already connecting!"), + message: Text("You are already connecting via this one-time link!"), + dismissButton: .default(Text("OK")) { cleanup?() } + ) + case let .ownContactAddressConfirmConnect(connectionLink, connectionPlan, incognito): + return Alert( + title: Text("Connect to yourself?"), + message: Text("This is your own SimpleX address!"), + primaryButton: .destructive( + Text(incognito ? "Connect incognito" : "Connect"), + action: { connectViaLink(connectionLink, connectionPlan: connectionPlan, dismiss: dismiss, incognito: incognito, cleanup: cleanup) } + ), + secondaryButton: .cancel() { cleanup?() } + ) + case let .contactAddressConnectingConfirmReconnect(connectionLink, connectionPlan, incognito): + return Alert( + title: Text("Repeat connection request?"), + message: Text("You have already requested connection via this address!"), + primaryButton: .destructive( + Text(incognito ? "Connect incognito" : "Connect"), + action: { connectViaLink(connectionLink, connectionPlan: connectionPlan, dismiss: dismiss, incognito: incognito, cleanup: cleanup) } + ), + secondaryButton: .cancel() { cleanup?() } + ) + case let .groupLinkConfirmConnect(connectionLink, connectionPlan, incognito): + return Alert( + title: Text("Join group?"), + message: Text("You will connect to all group members."), + primaryButton: .default( + Text(incognito ? "Join incognito" : "Join"), + action: { connectViaLink(connectionLink, connectionPlan: connectionPlan, dismiss: dismiss, incognito: incognito, cleanup: cleanup) } + ), + secondaryButton: .cancel() { cleanup?() } + ) + case let .groupLinkConnectingConfirmReconnect(connectionLink, connectionPlan, incognito): + return Alert( + title: Text("Repeat join request?"), + message: Text("You are already joining the group via this link!"), + primaryButton: .destructive( + Text(incognito ? "Join incognito" : "Join"), + action: { connectViaLink(connectionLink, connectionPlan: connectionPlan, dismiss: dismiss, incognito: incognito, cleanup: cleanup) } + ), + secondaryButton: .cancel() { cleanup?() } + ) + case let .groupLinkConnecting(_, groupInfo): + if let groupInfo = groupInfo { + return Alert( + title: Text("Group already exists!"), + message: Text("You are already joining the group \(groupInfo.displayName)."), + dismissButton: .default(Text("OK")) { cleanup?() } + ) + } else { + return Alert( + title: Text("Already joining the group!"), + message: Text("You are already joining the group via this link."), + dismissButton: .default(Text("OK")) { cleanup?() } + ) + } + } +} + +enum PlanAndConnectActionSheet: Identifiable { + case askCurrentOrIncognitoProfile(connectionLink: String, connectionPlan: ConnectionPlan?, title: LocalizedStringKey) + case askCurrentOrIncognitoProfileDestructive(connectionLink: String, connectionPlan: ConnectionPlan, title: LocalizedStringKey) + case askCurrentOrIncognitoProfileConnectContactViaAddress(contact: Contact) + case ownGroupLinkConfirmConnect(connectionLink: String, connectionPlan: ConnectionPlan, incognito: Bool?, groupInfo: GroupInfo) + + var id: String { + switch self { + case let .askCurrentOrIncognitoProfile(connectionLink, _, _): return "askCurrentOrIncognitoProfile \(connectionLink)" + case let .askCurrentOrIncognitoProfileDestructive(connectionLink, _, _): return "askCurrentOrIncognitoProfileDestructive \(connectionLink)" + case let .askCurrentOrIncognitoProfileConnectContactViaAddress(contact): return "askCurrentOrIncognitoProfileConnectContactViaAddress \(contact.contactId)" + case let .ownGroupLinkConfirmConnect(connectionLink, _, _, _): return "ownGroupLinkConfirmConnect \(connectionLink)" + } + } +} + +func planAndConnectActionSheet(_ sheet: PlanAndConnectActionSheet, dismiss: Bool, cleanup: (() -> Void)? = nil) -> ActionSheet { + switch sheet { + case let .askCurrentOrIncognitoProfile(connectionLink, connectionPlan, title): + return ActionSheet( + title: Text(title), + buttons: [ + .default(Text("Use current profile")) { connectViaLink(connectionLink, connectionPlan: connectionPlan, dismiss: dismiss, incognito: false, cleanup: cleanup) }, + .default(Text("Use new incognito profile")) { connectViaLink(connectionLink, connectionPlan: connectionPlan, dismiss: dismiss, incognito: true, cleanup: cleanup) }, + .cancel() { cleanup?() } + ] + ) + case let .askCurrentOrIncognitoProfileDestructive(connectionLink, connectionPlan, title): + return ActionSheet( + title: Text(title), + buttons: [ + .destructive(Text("Use current profile")) { connectViaLink(connectionLink, connectionPlan: connectionPlan, dismiss: dismiss, incognito: false, cleanup: cleanup) }, + .destructive(Text("Use new incognito profile")) { connectViaLink(connectionLink, connectionPlan: connectionPlan, dismiss: dismiss, incognito: true, cleanup: cleanup) }, + .cancel() { cleanup?() } + ] + ) + case let .askCurrentOrIncognitoProfileConnectContactViaAddress(contact): + return ActionSheet( + title: Text("Connect with \(contact.chatViewName)"), + buttons: [ + .default(Text("Use current profile")) { connectContactViaAddress_(contact, dismiss: dismiss, incognito: false, cleanup: cleanup) }, + .default(Text("Use new incognito profile")) { connectContactViaAddress_(contact, dismiss: dismiss, incognito: true, cleanup: cleanup) }, + .cancel() { cleanup?() } + ] + ) + case let .ownGroupLinkConfirmConnect(connectionLink, connectionPlan, incognito, groupInfo): + if let incognito = incognito { + return ActionSheet( + title: Text("Join your group?\nThis is your link for group \(groupInfo.displayName)!"), + buttons: [ + .default(Text("Open group")) { openKnownGroup(groupInfo, dismiss: dismiss, showAlreadyExistsAlert: nil) }, + .destructive(Text(incognito ? "Join incognito" : "Join with current profile")) { connectViaLink(connectionLink, connectionPlan: connectionPlan, dismiss: dismiss, incognito: incognito, cleanup: cleanup) }, + .cancel() { cleanup?() } + ] + ) + } else { + return ActionSheet( + title: Text("Join your group?\nThis is your link for group \(groupInfo.displayName)!"), + buttons: [ + .default(Text("Open group")) { openKnownGroup(groupInfo, dismiss: dismiss, showAlreadyExistsAlert: nil) }, + .destructive(Text("Use current profile")) { connectViaLink(connectionLink, connectionPlan: connectionPlan, dismiss: dismiss, incognito: false, cleanup: cleanup) }, + .destructive(Text("Use new incognito profile")) { connectViaLink(connectionLink, connectionPlan: connectionPlan, dismiss: dismiss, incognito: true, cleanup: cleanup) }, + .cancel() { cleanup?() } + ] + ) + } + } +} + +func planAndConnect( + _ connectionLink: String, + showAlert: @escaping (PlanAndConnectAlert) -> Void, + showActionSheet: @escaping (PlanAndConnectActionSheet) -> Void, + dismiss: Bool, + incognito: Bool?, + cleanup: (() -> Void)? = nil, + filterKnownContact: ((Contact) -> Void)? = nil, + filterKnownGroup: ((GroupInfo) -> Void)? = nil +) { + Task { + do { + let connectionPlan = try await apiConnectPlan(connReq: connectionLink) + switch connectionPlan { + case let .invitationLink(ilp): + switch ilp { + case .ok: + logger.debug("planAndConnect, .invitationLink, .ok, incognito=\(incognito?.description ?? "nil")") + if let incognito = incognito { + connectViaLink(connectionLink, connectionPlan: connectionPlan, dismiss: dismiss, incognito: incognito, cleanup: cleanup) + } else { + showActionSheet(.askCurrentOrIncognitoProfile(connectionLink: connectionLink, connectionPlan: connectionPlan, title: "Connect via one-time link")) + } + case .ownLink: + logger.debug("planAndConnect, .invitationLink, .ownLink, incognito=\(incognito?.description ?? "nil")") + if let incognito = incognito { + showAlert(.ownInvitationLinkConfirmConnect(connectionLink: connectionLink, connectionPlan: connectionPlan, incognito: incognito)) + } else { + showActionSheet(.askCurrentOrIncognitoProfileDestructive(connectionLink: connectionLink, connectionPlan: connectionPlan, title: "Connect to yourself?\nThis is your own one-time link!")) + } + case let .connecting(contact_): + logger.debug("planAndConnect, .invitationLink, .connecting, incognito=\(incognito?.description ?? "nil")") + if let contact = contact_ { + if let f = filterKnownContact { + f(contact) + } else { + openKnownContact(contact, dismiss: dismiss) { AlertManager.shared.showAlert(contactAlreadyConnectingAlert(contact)) } + } + } else { + showAlert(.invitationLinkConnecting(connectionLink: connectionLink)) + } + case let .known(contact): + logger.debug("planAndConnect, .invitationLink, .known, incognito=\(incognito?.description ?? "nil")") + if let f = filterKnownContact { + f(contact) + } else { + openKnownContact(contact, dismiss: dismiss) { AlertManager.shared.showAlert(contactAlreadyExistsAlert(contact)) } + } + } + case let .contactAddress(cap): + switch cap { + case .ok: + logger.debug("planAndConnect, .contactAddress, .ok, incognito=\(incognito?.description ?? "nil")") + if let incognito = incognito { + connectViaLink(connectionLink, connectionPlan: connectionPlan, dismiss: dismiss, incognito: incognito, cleanup: cleanup) + } else { + showActionSheet(.askCurrentOrIncognitoProfile(connectionLink: connectionLink, connectionPlan: connectionPlan, title: "Connect via contact address")) + } + case .ownLink: + logger.debug("planAndConnect, .contactAddress, .ownLink, incognito=\(incognito?.description ?? "nil")") + if let incognito = incognito { + showAlert(.ownContactAddressConfirmConnect(connectionLink: connectionLink, connectionPlan: connectionPlan, incognito: incognito)) + } else { + showActionSheet(.askCurrentOrIncognitoProfileDestructive(connectionLink: connectionLink, connectionPlan: connectionPlan, title: "Connect to yourself?\nThis is your own SimpleX address!")) + } + case .connectingConfirmReconnect: + logger.debug("planAndConnect, .contactAddress, .connectingConfirmReconnect, incognito=\(incognito?.description ?? "nil")") + if let incognito = incognito { + showAlert(.contactAddressConnectingConfirmReconnect(connectionLink: connectionLink, connectionPlan: connectionPlan, incognito: incognito)) + } else { + showActionSheet(.askCurrentOrIncognitoProfileDestructive(connectionLink: connectionLink, connectionPlan: connectionPlan, title: "You have already requested connection!\nRepeat connection request?")) + } + case let .connectingProhibit(contact): + logger.debug("planAndConnect, .contactAddress, .connectingProhibit, incognito=\(incognito?.description ?? "nil")") + if let f = filterKnownContact { + f(contact) + } else { + openKnownContact(contact, dismiss: dismiss) { AlertManager.shared.showAlert(contactAlreadyConnectingAlert(contact)) } + } + case let .known(contact): + logger.debug("planAndConnect, .contactAddress, .known, incognito=\(incognito?.description ?? "nil")") + if let f = filterKnownContact { + f(contact) + } else { + openKnownContact(contact, dismiss: dismiss) { AlertManager.shared.showAlert(contactAlreadyExistsAlert(contact)) } + } + case let .contactViaAddress(contact): + logger.debug("planAndConnect, .contactAddress, .contactViaAddress, incognito=\(incognito?.description ?? "nil")") + if let incognito = incognito { + connectContactViaAddress_(contact, dismiss: dismiss, incognito: incognito, cleanup: cleanup) + } else { + showActionSheet(.askCurrentOrIncognitoProfileConnectContactViaAddress(contact: contact)) + } + } + case let .groupLink(glp): + switch glp { + case .ok: + if let incognito = incognito { + showAlert(.groupLinkConfirmConnect(connectionLink: connectionLink, connectionPlan: connectionPlan, incognito: incognito)) + } else { + showActionSheet(.askCurrentOrIncognitoProfile(connectionLink: connectionLink, connectionPlan: connectionPlan, title: "Join group")) + } + case let .ownLink(groupInfo): + logger.debug("planAndConnect, .groupLink, .ownLink, incognito=\(incognito?.description ?? "nil")") + if let f = filterKnownGroup { + f(groupInfo) + } + showActionSheet(.ownGroupLinkConfirmConnect(connectionLink: connectionLink, connectionPlan: connectionPlan, incognito: incognito, groupInfo: groupInfo)) + case .connectingConfirmReconnect: + logger.debug("planAndConnect, .groupLink, .connectingConfirmReconnect, incognito=\(incognito?.description ?? "nil")") + if let incognito = incognito { + showAlert(.groupLinkConnectingConfirmReconnect(connectionLink: connectionLink, connectionPlan: connectionPlan, incognito: incognito)) + } else { + showActionSheet(.askCurrentOrIncognitoProfileDestructive(connectionLink: connectionLink, connectionPlan: connectionPlan, title: "You are already joining the group!\nRepeat join request?")) + } + case let .connectingProhibit(groupInfo_): + logger.debug("planAndConnect, .groupLink, .connectingProhibit, incognito=\(incognito?.description ?? "nil")") + showAlert(.groupLinkConnecting(connectionLink: connectionLink, groupInfo: groupInfo_)) + case let .known(groupInfo): + logger.debug("planAndConnect, .groupLink, .known, incognito=\(incognito?.description ?? "nil")") + if let f = filterKnownGroup { + f(groupInfo) + } else { + openKnownGroup(groupInfo, dismiss: dismiss) { AlertManager.shared.showAlert(groupAlreadyExistsAlert(groupInfo)) } + } + } + } + } catch { + logger.debug("planAndConnect, plan error") + if let incognito = incognito { + connectViaLink(connectionLink, connectionPlan: nil, dismiss: dismiss, incognito: incognito, cleanup: cleanup) + } else { + showActionSheet(.askCurrentOrIncognitoProfile(connectionLink: connectionLink, connectionPlan: nil, title: "Connect via link")) + } + } + } +} + +private func connectContactViaAddress_(_ contact: Contact, dismiss: Bool, incognito: Bool, cleanup: (() -> Void)? = nil) { + Task { + if dismiss { + DispatchQueue.main.async { + dismissAllSheets(animated: true) + } + } + _ = await connectContactViaAddress(contact.contactId, incognito) + cleanup?() + } +} + +private func connectViaLink( + _ connectionLink: String, + connectionPlan: ConnectionPlan?, + dismiss: Bool, + incognito: Bool, + cleanup: (() -> Void)? +) { + Task { + if let (connReqType, pcc) = await apiConnect(incognito: incognito, connReq: connectionLink) { + await MainActor.run { + ChatModel.shared.updateContactConnection(pcc) + } + let crt: ConnReqType + if let plan = connectionPlan { + crt = planToConnReqType(plan) + } else { + crt = connReqType + } + DispatchQueue.main.async { + if dismiss { + dismissAllSheets(animated: true) { + AlertManager.shared.showAlert(connReqSentAlert(crt)) + } + } else { + AlertManager.shared.showAlert(connReqSentAlert(crt)) + } + } + } else { + if dismiss { + DispatchQueue.main.async { + dismissAllSheets(animated: true) + } + } + } + cleanup?() + } +} + +func openKnownContact(_ contact: Contact, dismiss: Bool, showAlreadyExistsAlert: (() -> Void)?) { + Task { + let m = ChatModel.shared + if let c = m.getContactChat(contact.contactId) { + DispatchQueue.main.async { + if dismiss { + dismissAllSheets(animated: true) { + m.chatId = c.id + showAlreadyExistsAlert?() + } + } else { + m.chatId = c.id + showAlreadyExistsAlert?() + } + } + } + } +} + +func openKnownGroup(_ groupInfo: GroupInfo, dismiss: Bool, showAlreadyExistsAlert: (() -> Void)?) { + Task { + let m = ChatModel.shared + if let g = m.getGroupChat(groupInfo.groupId) { + DispatchQueue.main.async { + if dismiss { + dismissAllSheets(animated: true) { + m.chatId = g.id + showAlreadyExistsAlert?() + } + } else { + m.chatId = g.id + showAlreadyExistsAlert?() + } + } + } + } +} + +func contactAlreadyConnectingAlert(_ contact: Contact) -> Alert { + mkAlert( + title: "Contact already exists", + message: "You are already connecting to \(contact.displayName)." + ) +} + +func groupAlreadyExistsAlert(_ groupInfo: GroupInfo) -> Alert { + mkAlert( + title: "Group already exists", + message: "You are already in group \(groupInfo.displayName)." + ) +} + +enum ConnReqType: Equatable { + case invitation + case contact + case groupLink + + var connReqSentText: LocalizedStringKey { + switch self { + case .invitation: return "You will be connected when your contact's device is online, please wait or check later!" + case .contact: return "You will be connected when your connection request is accepted, please wait or check later!" + case .groupLink: return "You will be connected when group link host's device is online, please wait or check later!" + } + } +} + +private func planToConnReqType(_ connectionPlan: ConnectionPlan) -> ConnReqType { + switch connectionPlan { + case .invitationLink: return .invitation + case .contactAddress: return .contact + case .groupLink: return .groupLink + } +} + +func connReqSentAlert(_ type: ConnReqType) -> Alert { + return mkAlert( + title: "Connection request sent!", + message: type.connReqSentText + ) +} + +#Preview { + NewChatView( + selection: .invite + ) +} diff --git a/apps/ios/Shared/Views/NewChat/PasteToConnectView.swift b/apps/ios/Shared/Views/NewChat/PasteToConnectView.swift deleted file mode 100644 index 7c272fb631..0000000000 --- a/apps/ios/Shared/Views/NewChat/PasteToConnectView.swift +++ /dev/null @@ -1,106 +0,0 @@ -// -// PasteToConnectView.swift -// SimpleX (iOS) -// -// Created by Ian Davies on 22/04/2022. -// Copyright © 2022 SimpleX Chat. All rights reserved. -// - -import SwiftUI -import SimpleXChat - -struct PasteToConnectView: View { - @Environment(\.dismiss) var dismiss: DismissAction - @State private var connectionLink: String = "" - @AppStorage(GROUP_DEFAULT_INCOGNITO, store: groupDefaults) private var incognitoDefault = false - @FocusState private var linkEditorFocused: Bool - @State private var alert: PlanAndConnectAlert? - @State private var sheet: PlanAndConnectActionSheet? - - var body: some View { - List { - Text("Connect via link") - .font(.largeTitle) - .bold() - .fixedSize(horizontal: false, vertical: true) - .listRowBackground(Color.clear) - .listRowSeparator(.hidden) - .listRowInsets(EdgeInsets(top: 0, leading: 0, bottom: 0, trailing: 0)) - .onTapGesture { linkEditorFocused = false } - - Section { - linkEditor() - - Button { - if connectionLink == "" { - connectionLink = UIPasteboard.general.string ?? "" - } else { - connectionLink = "" - } - } label: { - if connectionLink == "" { - settingsRow("doc.plaintext") { Text("Paste") } - } else { - settingsRow("multiply") { Text("Clear") } - } - } - - Button { - connect() - } label: { - settingsRow("link") { Text("Connect") } - } - .disabled(connectionLink == "" || connectionLink.trimmingCharacters(in: .whitespaces).firstIndex(of: " ") != nil) - - IncognitoToggle(incognitoEnabled: $incognitoDefault) - } footer: { - VStack(alignment: .leading, spacing: 4) { - sharedProfileInfo(incognitoDefault) - Text("You can also connect by clicking the link. If it opens in the browser, click **Open in mobile app** button.") - } - .frame(maxWidth: .infinity, alignment: .leading) - } - } - .alert(item: $alert) { a in planAndConnectAlert(a, dismiss: true) } - .actionSheet(item: $sheet) { s in planAndConnectActionSheet(s, dismiss: true) } - } - - private func linkEditor() -> some View { - ZStack { - Group { - if connectionLink.isEmpty { - TextEditor(text: Binding.constant(NSLocalizedString("Paste the link you received to connect with your contact.", comment: "placeholder"))) - .foregroundColor(.secondary) - .disabled(true) - } - TextEditor(text: $connectionLink) - .onSubmit(connect) - .textInputAutocapitalization(.never) - .disableAutocorrection(true) - .focused($linkEditorFocused) - } - .allowsTightening(false) - .padding(.horizontal, -5) - .padding(.top, -8) - .frame(height: 180, alignment: .topLeading) - .frame(maxWidth: .infinity, alignment: .leading) - } - } - - private func connect() { - let link = connectionLink.trimmingCharacters(in: .whitespaces) - planAndConnect( - link, - showAlert: { alert = $0 }, - showActionSheet: { sheet = $0 }, - dismiss: true, - incognito: incognitoDefault - ) - } -} - -struct PasteToConnectView_Previews: PreviewProvider { - static var previews: some View { - PasteToConnectView() - } -} diff --git a/apps/ios/Shared/Views/NewChat/QRCode.swift b/apps/ios/Shared/Views/NewChat/QRCode.swift index 3ddb85079c..e3bae9287a 100644 --- a/apps/ios/Shared/Views/NewChat/QRCode.swift +++ b/apps/ios/Shared/Views/NewChat/QRCode.swift @@ -24,9 +24,10 @@ struct SimpleXLinkQRCode: View { let uri: String var withLogo: Bool = true var tintColor = UIColor(red: 0.023, green: 0.176, blue: 0.337, alpha: 1) + var onShare: (() -> Void)? = nil var body: some View { - QRCode(uri: simplexChatLink(uri), withLogo: withLogo, tintColor: tintColor) + QRCode(uri: simplexChatLink(uri), withLogo: withLogo, tintColor: tintColor, onShare: onShare) } } @@ -40,6 +41,7 @@ struct QRCode: View { let uri: String var withLogo: Bool = true var tintColor = UIColor(red: 0.023, green: 0.176, blue: 0.337, alpha: 1) + var onShare: (() -> Void)? = nil @State private var image: UIImage? = nil @State private var makeScreenshotFunc: () -> Void = {} @@ -65,6 +67,7 @@ struct QRCode: View { makeScreenshotFunc = { let size = CGSizeMake(1024 / UIScreen.main.scale, 1024 / UIScreen.main.scale) showShareSheet(items: [makeScreenshot(geo.frame(in: .local).origin, size)]) + onShare?() } } .frame(width: geo.size.width, height: geo.size.height) diff --git a/apps/ios/Shared/Views/NewChat/ScanToConnectView.swift b/apps/ios/Shared/Views/NewChat/ScanToConnectView.swift deleted file mode 100644 index 7f3f5e02f8..0000000000 --- a/apps/ios/Shared/Views/NewChat/ScanToConnectView.swift +++ /dev/null @@ -1,79 +0,0 @@ -// -// ConnectContactView.swift -// SimpleX -// -// Created by Evgeny Poberezkin on 29/01/2022. -// Copyright © 2022 SimpleX Chat. All rights reserved. -// - -import SwiftUI -import SimpleXChat -import CodeScanner - -struct ScanToConnectView: View { - @Environment(\.dismiss) var dismiss: DismissAction - @AppStorage(GROUP_DEFAULT_INCOGNITO, store: groupDefaults) private var incognitoDefault = false - @State private var alert: PlanAndConnectAlert? - @State private var sheet: PlanAndConnectActionSheet? - - var body: some View { - ScrollView { - VStack(alignment: .leading) { - Text("Scan QR code") - .font(.largeTitle) - .bold() - .fixedSize(horizontal: false, vertical: true) - .padding(.vertical) - - CodeScannerView(codeTypes: [.qr], scanMode: .continuous, completion: processQRCode) - .aspectRatio(1, contentMode: .fit) - .cornerRadius(12) - - IncognitoToggle(incognitoEnabled: $incognitoDefault) - .padding(.horizontal) - .padding(.vertical, 6) - .background( - RoundedRectangle(cornerRadius: 12, style: .continuous) - .fill(Color(uiColor: .systemBackground)) - ) - .padding(.top) - - VStack(alignment: .leading, spacing: 4) { - sharedProfileInfo(incognitoDefault) - Text("If you cannot meet in person, you can **scan QR code in the video call**, or your contact can share an invitation link.") - } - .frame(maxWidth: .infinity, alignment: .leading) - .font(.footnote) - .foregroundColor(.secondary) - .padding(.horizontal) - } - .padding() - .frame(maxWidth: .infinity, maxHeight: .infinity, alignment: .top) - } - .background(Color(.systemGroupedBackground)) - .alert(item: $alert) { a in planAndConnectAlert(a, dismiss: true) } - .actionSheet(item: $sheet) { s in planAndConnectActionSheet(s, dismiss: true) } - } - - func processQRCode(_ resp: Result<ScanResult, ScanError>) { - switch resp { - case let .success(r): - planAndConnect( - r.string, - showAlert: { alert = $0 }, - showActionSheet: { sheet = $0 }, - dismiss: true, - incognito: incognitoDefault - ) - case let .failure(e): - logger.error("ConnectContactView.processQRCode QR code error: \(e.localizedDescription)") - dismiss() - } - } -} - -struct ConnectContactView_Previews: PreviewProvider { - static var previews: some View { - ScanToConnectView() - } -} diff --git a/apps/ios/Shared/Views/Onboarding/CreateProfile.swift b/apps/ios/Shared/Views/Onboarding/CreateProfile.swift index f5db37dacf..3f835e25d4 100644 --- a/apps/ios/Shared/Views/Onboarding/CreateProfile.swift +++ b/apps/ios/Shared/Views/Onboarding/CreateProfile.swift @@ -11,12 +11,14 @@ import SimpleXChat enum UserProfileAlert: Identifiable { case duplicateUserError + case invalidDisplayNameError case createUserError(error: LocalizedStringKey) case invalidNameError(validName: String) var id: String { switch self { case .duplicateUserError: return "duplicateUserError" + case .invalidDisplayNameError: return "invalidDisplayNameError" case .createUserError: return "createUserError" case let .invalidNameError(validName): return "invalidNameError \(validName)" } @@ -187,6 +189,12 @@ private func createProfile(_ displayName: String, showAlert: (UserProfileAlert) } else { showAlert(.duplicateUserError) } + case .chatCmdError(_, .error(.invalidDisplayName)): + if m.currentUser == nil { + AlertManager.shared.showAlert(invalidDisplayNameAlert) + } else { + showAlert(.invalidDisplayNameError) + } default: let err: LocalizedStringKey = "Error: \(responseError(error))" if m.currentUser == nil { @@ -207,6 +215,7 @@ private func canCreateProfile(_ displayName: String) -> Bool { func userProfileAlert(_ alert: UserProfileAlert, _ displayName: Binding<String>) -> Alert { switch alert { case .duplicateUserError: return duplicateUserAlert + case .invalidDisplayNameError: return invalidDisplayNameAlert case let .createUserError(err): return creatUserErrorAlert(err) case let .invalidNameError(name): return createInvalidNameAlert(name, displayName) } @@ -219,6 +228,13 @@ private var duplicateUserAlert: Alert { ) } +private var invalidDisplayNameAlert: Alert { + Alert( + title: Text("Invalid display name!"), + message: Text("This display name is invalid. Please choose another name.") + ) +} + private func creatUserErrorAlert(_ err: LocalizedStringKey) -> Alert { Alert( title: Text("Error creating profile!"), diff --git a/apps/ios/Shared/Views/Onboarding/WhatsNewView.swift b/apps/ios/Shared/Views/Onboarding/WhatsNewView.swift index 59c2b25b6d..ece10e46dd 100644 --- a/apps/ios/Shared/Views/Onboarding/WhatsNewView.swift +++ b/apps/ios/Shared/Views/Onboarding/WhatsNewView.swift @@ -314,6 +314,37 @@ private let versionDescriptions: [VersionDescription] = [ ), ] ), + VersionDescription( + version: "v5.5", + post: URL(string: "https://simplex.chat/blog/20240124-simplex-chat-infrastructure-costs-v5-5-simplex-ux-private-notes-group-history.html"), + features: [ + FeatureDescription( + icon: "folder", + title: "Private notes", + description: "With encrypted files and media." + ), + FeatureDescription( + icon: "link", + title: "Paste link to connect!", + description: "Search bar accepts invitation links." + ), + FeatureDescription( + icon: "bubble.left.and.bubble.right", + title: "Join group conversations", + description: "Recent history and improved [directory bot](simplex:/contact#/?v=1-4&smp=smp%3A%2F%2Fu2dS9sG8nMNURyZwqASV4yROM28Er0luVTx5X1CsMrU%3D%40smp4.simplex.im%2FeXSPwqTkKyDO3px4fLf1wx3MvPdjdLW3%23%2F%3Fv%3D1-2%26dh%3DMCowBQYDK2VuAyEAaiv6MkMH44L2TcYrt_CsX3ZvM11WgbMEUn0hkIKTOho%253D%26srv%3Do5vmywmrnaxalvz6wi3zicyftgio6psuvyniis6gco6bp6ekl4cqj4id.onion)." + ), + FeatureDescription( + icon: "battery.50", + title: "Improved message delivery", + description: "With reduced battery usage." + ), + FeatureDescription( + icon: "character", + title: "Turkish interface", + description: "Thanks to the users – [contribute via Weblate](https://github.com/simplex-chat/simplex-chat/tree/stable#help-translating-simplex-chat)!" + ), + ] + ) ] private let lastVersion = versionDescriptions.last!.version diff --git a/apps/ios/Shared/Views/UserSettings/IncognitoHelp.swift b/apps/ios/Shared/Views/UserSettings/IncognitoHelp.swift index 20dadb7954..fc478596a9 100644 --- a/apps/ios/Shared/Views/UserSettings/IncognitoHelp.swift +++ b/apps/ios/Shared/Views/UserSettings/IncognitoHelp.swift @@ -10,24 +10,23 @@ import SwiftUI struct IncognitoHelp: View { var body: some View { - VStack(alignment: .leading) { + List { Text("Incognito mode") .font(.largeTitle) .bold() + .fixedSize(horizontal: false, vertical: true) .padding(.vertical) - ScrollView { - VStack(alignment: .leading) { - Group { - Text("Incognito mode protects your privacy by using a new random profile for each contact.") - Text("It allows having many anonymous connections without any shared data between them in a single chat profile.") - Text("When you share an incognito profile with somebody, this profile will be used for the groups they invite you to.") - } - .padding(.bottom) - } + .listRowBackground(Color.clear) + .listRowSeparator(.hidden) + .listRowInsets(EdgeInsets(top: 0, leading: 0, bottom: 0, trailing: 0)) + VStack(alignment: .leading, spacing: 18) { + Text("Incognito mode protects your privacy by using a new random profile for each contact.") + Text("It allows having many anonymous connections without any shared data between them in a single chat profile.") + Text("When you share an incognito profile with somebody, this profile will be used for the groups they invite you to.") + Text("Read more in [User Guide](https://simplex.chat/docs/guide/chat-profiles.html#incognito-mode).") } + .listRowBackground(Color.clear) } - .frame(maxWidth: .infinity) - .padding() } } diff --git a/apps/ios/Shared/Views/UserSettings/PreferencesView.swift b/apps/ios/Shared/Views/UserSettings/PreferencesView.swift index 960afb6d38..2e560f8578 100644 --- a/apps/ios/Shared/Views/UserSettings/PreferencesView.swift +++ b/apps/ios/Shared/Views/UserSettings/PreferencesView.swift @@ -63,7 +63,6 @@ struct PreferencesView: View { private func featureFooter(_ feature: ChatFeature, _ allowFeature: Binding<FeatureAllowed>) -> some View { Text(feature.allowDescription(allowFeature.wrappedValue)) - .frame(height: 36, alignment: .topLeading) } private func savePreferences() { diff --git a/apps/ios/Shared/Views/UserSettings/PrivacySettings.swift b/apps/ios/Shared/Views/UserSettings/PrivacySettings.swift index d8ff2c2f89..8d13c6fb39 100644 --- a/apps/ios/Shared/Views/UserSettings/PrivacySettings.swift +++ b/apps/ios/Shared/Views/UserSettings/PrivacySettings.swift @@ -491,14 +491,23 @@ struct SimplexLockView: View { showLAAlert(.laPasscodeNotChangedAlert) } case .enableSelfDestruct: - SetAppPasscodeView(passcodeKeychain: kcSelfDestructPassword, title: "Set passcode", reason: NSLocalizedString("Enable self-destruct passcode", comment: "set passcode view")) { + SetAppPasscodeView( + passcodeKeychain: kcSelfDestructPassword, + prohibitedPasscodeKeychain: kcAppPassword, + title: "Set passcode", + reason: NSLocalizedString("Enable self-destruct passcode", comment: "set passcode view") + ) { updateSelfDestruct() showLAAlert(.laSelfDestructPasscodeSetAlert) } cancel: { revertSelfDestruct() } case .changeSelfDestructPasscode: - SetAppPasscodeView(passcodeKeychain: kcSelfDestructPassword, reason: NSLocalizedString("Change self-destruct passcode", comment: "set passcode view")) { + SetAppPasscodeView( + passcodeKeychain: kcSelfDestructPassword, + prohibitedPasscodeKeychain: kcAppPassword, + reason: NSLocalizedString("Change self-destruct passcode", comment: "set passcode view") + ) { showLAAlert(.laSelfDestructPasscodeChangedAlert) } cancel: { showLAAlert(.laPasscodeNotChangedAlert) diff --git a/apps/ios/Shared/Views/UserSettings/SettingsView.swift b/apps/ios/Shared/Views/UserSettings/SettingsView.swift index f889d9c394..a691e6afc9 100644 --- a/apps/ios/Shared/Views/UserSettings/SettingsView.swift +++ b/apps/ios/Shared/Views/UserSettings/SettingsView.swift @@ -95,6 +95,12 @@ let appDefaults: [String: Any] = [ DEFAULT_CONNECT_REMOTE_VIA_MULTICAST_AUTO: true, ] +// not used anymore +enum ConnectViaLinkTab: String { + case scan + case paste +} + enum SimpleXLinkMode: String, Identifiable { case description case full @@ -153,37 +159,42 @@ struct SettingsView: View { } @ViewBuilder func settingsView() -> some View { - let user: User = chatModel.currentUser! + let user = chatModel.currentUser NavigationView { List { Section("You") { - NavigationLink { - UserProfile() - .navigationTitle("Your current profile") - } label: { - ProfilePreview(profileOf: user) - .padding(.leading, -8) + if let user = user { + NavigationLink { + UserProfile() + .navigationTitle("Your current profile") + } label: { + ProfilePreview(profileOf: user) + .padding(.leading, -8) + } } NavigationLink { - UserProfilesView() + UserProfilesView(showSettings: $showSettings) } label: { settingsRow("person.crop.rectangle.stack") { Text("Your chat profiles") } } - NavigationLink { - UserAddressView(shareViaProfile: chatModel.currentUser!.addressShared) - .navigationTitle("SimpleX address") - .navigationBarTitleDisplayMode(.large) - } label: { - settingsRow("qrcode") { Text("Your SimpleX address") } - } - NavigationLink { - PreferencesView(profile: user.profile, preferences: user.fullPreferences, currentPreferences: user.fullPreferences) - .navigationTitle("Your preferences") - } label: { - settingsRow("switch.2") { Text("Chat preferences") } + if let user = user { + NavigationLink { + UserAddressView(shareViaProfile: user.addressShared) + .navigationTitle("SimpleX address") + .navigationBarTitleDisplayMode(.large) + } label: { + settingsRow("qrcode") { Text("Your SimpleX address") } + } + + NavigationLink { + PreferencesView(profile: user.profile, preferences: user.fullPreferences, currentPreferences: user.fullPreferences) + .navigationTitle("Your preferences") + } label: { + settingsRow("switch.2") { Text("Chat preferences") } + } } NavigationLink { @@ -244,12 +255,14 @@ struct SettingsView: View { } Section("Help") { - NavigationLink { - ChatHelp(showSettings: $showSettings) - .navigationTitle("Welcome \(user.displayName)!") - .frame(maxHeight: .infinity, alignment: .top) - } label: { - settingsRow("questionmark") { Text("How to use it") } + if let user = user { + NavigationLink { + ChatHelp(showSettings: $showSettings) + .navigationTitle("Welcome \(user.displayName)!") + .frame(maxHeight: .infinity, alignment: .top) + } label: { + settingsRow("questionmark") { Text("How to use it") } + } } NavigationLink { WhatsNewView(viaSettings: true) diff --git a/apps/ios/Shared/Views/UserSettings/UserProfilesView.swift b/apps/ios/Shared/Views/UserSettings/UserProfilesView.swift index f6c7bf37e8..f2cac59dae 100644 --- a/apps/ios/Shared/Views/UserSettings/UserProfilesView.swift +++ b/apps/ios/Shared/Views/UserSettings/UserProfilesView.swift @@ -8,6 +8,7 @@ import SimpleXChat struct UserProfilesView: View { @EnvironmentObject private var m: ChatModel + @Binding var showSettings: Bool @Environment(\.editMode) private var editMode @AppStorage(DEFAULT_SHOW_HIDDEN_PROFILES_NOTICE) private var showHiddenProfilesNotice = true @AppStorage(DEFAULT_SHOW_MUTE_PROFILE_ALERT) private var showMuteProfileAlert = true @@ -25,7 +26,6 @@ struct UserProfilesView: View { private enum UserProfilesAlert: Identifiable { case deleteUser(user: User, delSMPQueues: Bool) - case cantDeleteLastUser case hiddenProfilesNotice case muteProfileAlert case activateUserError(error: String) @@ -34,7 +34,6 @@ struct UserProfilesView: View { var id: String { switch self { case let .deleteUser(user, delSMPQueues): return "deleteUser \(user.userId) \(delSMPQueues)" - case .cantDeleteLastUser: return "cantDeleteLastUser" case .hiddenProfilesNotice: return "hiddenProfilesNotice" case .muteProfileAlert: return "muteProfileAlert" case let .activateUserError(err): return "activateUserError \(err)" @@ -78,7 +77,7 @@ struct UserProfilesView: View { Section { let users = filteredUsers() let v = ForEach(users) { u in - userView(u.user, allowDelete: users.count > 1) + userView(u.user) } if #available(iOS 16, *) { v.onDelete { indexSet in @@ -146,13 +145,6 @@ struct UserProfilesView: View { }, secondaryButton: .cancel() ) - case .cantDeleteLastUser: - return Alert( - title: Text("Can't delete user profile!"), - message: m.users.count > 1 - ? Text("There should be at least one visible user profile.") - : Text("There should be at least one user profile.") - ) case .hiddenProfilesNotice: return Alert( title: Text("Make profile private!"), @@ -280,11 +272,21 @@ struct UserProfilesView: View { if let newActive = m.users.first(where: { u in !u.user.activeUser && !u.user.hidden }) { try await changeActiveUserAsync_(newActive.user.userId, viewPwd: nil) try await deleteUser() + } else { + // Deleting the last visible user while having hidden one(s) + try await deleteUser() + try await changeActiveUserAsync_(nil, viewPwd: nil) + await MainActor.run { + onboardingStageDefault.set(.step1_SimpleXInfo) + m.onboardingStage = .step1_SimpleXInfo + showSettings = false + } } } else { try await deleteUser() } } catch let error { + logger.error("Error deleting user profile: \(error)") let a = getErrorAlert(error, "Error deleting user profile") alert = .error(title: a.title, error: a.message) } @@ -295,7 +297,7 @@ struct UserProfilesView: View { } } - @ViewBuilder private func userView(_ user: User, allowDelete: Bool) -> some View { + @ViewBuilder private func userView(_ user: User) -> some View { let v = Button { Task { do { @@ -323,9 +325,7 @@ struct UserProfilesView: View { } } } - .disabled(user.activeUser) .foregroundColor(.primary) - .deleteDisabled(!allowDelete) .swipeActions(edge: .leading, allowsFullSwipe: true) { if user.hidden { Button("Unhide") { @@ -361,8 +361,6 @@ struct UserProfilesView: View { } if #available(iOS 16, *) { v - } else if !allowDelete { - v } else { v.swipeActions(edge: .trailing, allowsFullSwipe: true) { Button("Delete", role: .destructive) { @@ -373,12 +371,8 @@ struct UserProfilesView: View { } private func confirmDeleteUser(_ user: User) { - if m.users.count > 1 && (user.hidden || visibleUsersCount > 1) { - showDeleteConfirmation = true - userToDelete = user - } else { - alert = .cantDeleteLastUser - } + showDeleteConfirmation = true + userToDelete = user } private func setUserPrivacy(_ user: User, successAlert: UserProfilesAlert? = nil, _ api: @escaping () async throws -> User) { @@ -409,6 +403,6 @@ public func chatPasswordHash(_ pwd: String, _ salt: String) -> String { struct UserProfilesView_Previews: PreviewProvider { static var previews: some View { - UserProfilesView() + UserProfilesView(showSettings: Binding.constant(true)) } } diff --git a/apps/ios/SimpleX Localizations/bg.xcloc/Localized Contents/bg.xliff b/apps/ios/SimpleX Localizations/bg.xcloc/Localized Contents/bg.xliff index 7a2afea082..85e4ebb985 100644 --- a/apps/ios/SimpleX Localizations/bg.xcloc/Localized Contents/bg.xliff +++ b/apps/ios/SimpleX Localizations/bg.xcloc/Localized Contents/bg.xliff @@ -89,6 +89,7 @@ </trans-unit> <trans-unit id="%@ and %@" xml:space="preserve"> <source>%@ and %@</source> + <target>%@ и %@</target> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="%@ and %@ connected" xml:space="preserve"> @@ -103,6 +104,7 @@ </trans-unit> <trans-unit id="%@ connected" xml:space="preserve"> <source>%@ connected</source> + <target>%@ свързан</target> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="%@ is connected!" xml:space="preserve"> @@ -132,6 +134,7 @@ </trans-unit> <trans-unit id="%@, %@ and %lld members" xml:space="preserve"> <source>%@, %@ and %lld members</source> + <target>%@, %@ и %lld членове</target> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="%@, %@ and %lld other members connected" xml:space="preserve"> @@ -201,6 +204,7 @@ </trans-unit> <trans-unit id="%lld group events" xml:space="preserve"> <source>%lld group events</source> + <target>%lld групови събития</target> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="%lld members" xml:space="preserve"> @@ -210,14 +214,21 @@ </trans-unit> <trans-unit id="%lld messages blocked" xml:space="preserve"> <source>%lld messages blocked</source> + <target>%lld блокирани съобщения</target> + <note>No comment provided by engineer.</note> + </trans-unit> + <trans-unit id="%lld messages blocked by admin" xml:space="preserve"> + <source>%lld messages blocked by admin</source> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="%lld messages marked deleted" xml:space="preserve"> <source>%lld messages marked deleted</source> + <target>%lld съобщения, маркирани като изтрити</target> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="%lld messages moderated by %@" xml:space="preserve"> <source>%lld messages moderated by %@</source> + <target>%lld съобщения, модерирани от %@</target> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="%lld minutes" xml:space="preserve"> @@ -292,10 +303,12 @@ </trans-unit> <trans-unit id="(new)" xml:space="preserve"> <source>(new)</source> + <target>(ново)</target> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="(this device v%@)" xml:space="preserve"> <source>(this device v%@)</source> + <target>(това устройство v%@)</target> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id=")" xml:space="preserve"> @@ -303,14 +316,19 @@ <target>)</target> <note>No comment provided by engineer.</note> </trans-unit> + <trans-unit id="**Add contact**: to create a new invitation link, or connect via a link you received." xml:space="preserve"> + <source>**Add contact**: to create a new invitation link, or connect via a link you received.</source> + <target>**Добави контакт**: за създаване на нов линк или свързване чрез получен линк за връзка.</target> + <note>No comment provided by engineer.</note> + </trans-unit> <trans-unit id="**Add new contact**: to create your one-time QR Code for your contact." xml:space="preserve"> <source>**Add new contact**: to create your one-time QR Code or link for your contact.</source> <target>**Добави нов контакт**: за да създадете своя еднократен QR код или линк за вашия контакт.</target> <note>No comment provided by engineer.</note> </trans-unit> - <trans-unit id="**Create link / QR code** for your contact to use." xml:space="preserve"> - <source>**Create link / QR code** for your contact to use.</source> - <target>**Създай линк / QR код**, който вашият контакт да използва.</target> + <trans-unit id="**Create group**: to create a new group." xml:space="preserve"> + <source>**Create group**: to create a new group.</source> + <target>**Създай група**: за създаване на нова група.</target> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="**More private**: check new messages every 20 minutes. Device token is shared with SimpleX Chat server, but not how many contacts or messages you have." xml:space="preserve"> @@ -323,11 +341,6 @@ <target>**Най-поверително**: не използвайте сървъра за известия SimpleX Chat, периодично проверявайте съобщенията във фонов режим (зависи от това колко често използвате приложението).</target> <note>No comment provided by engineer.</note> </trans-unit> - <trans-unit id="**Paste received link** or open it in the browser and tap **Open in mobile app**." xml:space="preserve"> - <source>**Paste received link** or open it in the browser and tap **Open in mobile app**.</source> - <target>**Поставете получения линк** или го отворете в браузъра и докоснете **Отваряне в мобилно приложение**.</target> - <note>No comment provided by engineer.</note> - </trans-unit> <trans-unit id="**Please note**: you will NOT be able to recover or change passphrase if you lose it." xml:space="preserve"> <source>**Please note**: you will NOT be able to recover or change passphrase if you lose it.</source> <target>**Моля, обърнете внимание**: НЯМА да можете да възстановите или промените паролата, ако я загубите.</target> @@ -338,11 +351,6 @@ <target>**Препоръчително**: токенът на устройството и известията се изпращат до сървъра за уведомяване на SimpleX Chat, но не и съдържанието, размерът на съобщението или от кого е.</target> <note>No comment provided by engineer.</note> </trans-unit> - <trans-unit id="**Scan QR code**: to connect to your contact in person or via video call." xml:space="preserve"> - <source>**Scan QR code**: to connect to your contact in person or via video call.</source> - <target>**Сканирай QR код**: за да се свържете с вашия контакт лично или чрез видеообаждане.</target> - <note>No comment provided by engineer.</note> - </trans-unit> <trans-unit id="**Warning**: Instant push notifications require passphrase saved in Keychain." xml:space="preserve"> <source>**Warning**: Instant push notifications require passphrase saved in Keychain.</source> <target>**Внимание**: Незабавните push известия изискват парола, запазена в Keychain.</target> @@ -372,7 +380,7 @@ <source>- connect to [directory service](simplex:/contact#/?v=1-4&smp=smp%3A%2F%2Fu2dS9sG8nMNURyZwqASV4yROM28Er0luVTx5X1CsMrU%3D%40smp4.simplex.im%2FeXSPwqTkKyDO3px4fLf1wx3MvPdjdLW3%23%2F%3Fv%3D1-2%26dh%3DMCowBQYDK2VuAyEAaiv6MkMH44L2TcYrt_CsX3ZvM11WgbMEUn0hkIKTOho%253D%26srv%3Do5vmywmrnaxalvz6wi3zicyftgio6psuvyniis6gco6bp6ekl4cqj4id.onion) (BETA)! - delivery receipts (up to 20 members). - faster and more stable.</source> - <target>- свържете се с [директория за услуги](simplex:/contact#/?v=1-4&smp=smp%3A%2F%2Fu2dS9sG8nMNURyZwqASV4yROM28Er0luVTx5X1CsMrU%3D%40smp4.simplex.im%2FeXSPwqTkKyDO3px4fLf1wx3MvPdjd LW3%23%2F%3Fv%3D1-2%26dh %3DMCowBQYDK2VuAyEAaiv6MkMH44L2TcYrt_CsX3ZvM11WgbMEUn0hkIKTOho%253D%26srv%3Do5vmywmrnaxalvz6wi3zicyftgio6psuvyniis6gco6bp6ekl4cqj4id.onion) (БЕТА)! + <target>- свържете се с [директория за услуги](simplex:/contact#/?v=1-4&smp=smp%3A%2F%2Fu2dS9sG8nMNURyZwqASV4yROM28Er0luVTx5X1CsMrU%3D%40smp4.simplex.im%2FeXSPwqTkKyDO3px4fLf1wx3MvPdjdLW3%23%2F%3Fv%3D1-2%26dh%3DMCowBQYDK2VuAyEAaiv6MkMH44L2TcYrt_CsX3ZvM11WgbMEUn0hkIKTOho%253D%26srv%3Do5vmywmrnaxalvz6wi3zicyftgio6psuvyniis6gco6bp6ekl4cqj4id.onion) (БЕТА)! - потвърждениe за доставка (до 20 члена). - по-бързо и по-стабилно.</target> <note>No comment provided by engineer.</note> @@ -390,6 +398,9 @@ <source>- optionally notify deleted contacts. - profile names with spaces. - and more!</source> + <target>- по желание уведомете изтритите контакти. +- имена на профили с интервали. +- и още!</target> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="- voice messages up to 5 minutes. - custom time to disappear. - editing history." xml:space="preserve"> @@ -408,6 +419,7 @@ </trans-unit> <trans-unit id="0 sec" xml:space="preserve"> <source>0 sec</source> + <target>0 сек</target> <note>time to disappear</note> </trans-unit> <trans-unit id="0s" xml:space="preserve"> @@ -440,11 +452,6 @@ <target>1 седмица</target> <note>time interval</note> </trans-unit> - <trans-unit id="1-time link" xml:space="preserve"> - <source>1-time link</source> - <target>Еднократен линк</target> - <note>No comment provided by engineer.</note> - </trans-unit> <trans-unit id="5 minutes" xml:space="preserve"> <source>5 minutes</source> <target>5 минути</target> @@ -560,6 +567,11 @@ <target>Добавете адрес към вашия профил, така че вашите контакти да могат да го споделят с други хора. Актуализацията на профила ще бъде изпратена до вашите контакти.</target> <note>No comment provided by engineer.</note> </trans-unit> + <trans-unit id="Add contact" xml:space="preserve"> + <source>Add contact</source> + <target>Добави контакт</target> + <note>No comment provided by engineer.</note> + </trans-unit> <trans-unit id="Add preset servers" xml:space="preserve"> <source>Add preset servers</source> <target>Добави предварително зададени сървъри</target> @@ -630,6 +642,10 @@ <target>Всички членове на групата ще останат свързани.</target> <note>No comment provided by engineer.</note> </trans-unit> + <trans-unit id="All messages will be deleted - this cannot be undone!" xml:space="preserve"> + <source>All messages will be deleted - this cannot be undone!</source> + <note>No comment provided by engineer.</note> + </trans-unit> <trans-unit id="All messages will be deleted - this cannot be undone! The messages will be deleted ONLY for you." xml:space="preserve"> <source>All messages will be deleted - this cannot be undone! The messages will be deleted ONLY for you.</source> <target>Всички съобщения ще бъдат изтрити - това не може да бъде отменено! Съобщенията ще бъдат изтрити САМО за вас.</target> @@ -637,6 +653,7 @@ </trans-unit> <trans-unit id="All new messages from %@ will be hidden!" xml:space="preserve"> <source>All new messages from %@ will be hidden!</source> + <target>Всички нови съобщения от %@ ще бъдат скрити!</target> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="All your contacts will remain connected." xml:space="preserve"> @@ -664,9 +681,9 @@ <target>Позволи изчезващи съобщения само ако вашият контакт ги разрешава.</target> <note>No comment provided by engineer.</note> </trans-unit> - <trans-unit id="Allow irreversible message deletion only if your contact allows it to you." xml:space="preserve"> - <source>Allow irreversible message deletion only if your contact allows it to you.</source> - <target>Позволи необратимо изтриване на съобщение само ако вашият контакт го рарешава.</target> + <trans-unit id="Allow irreversible message deletion only if your contact allows it to you. (24 hours)" xml:space="preserve"> + <source>Allow irreversible message deletion only if your contact allows it to you. (24 hours)</source> + <target>Позволи необратимо изтриване на съобщение само ако вашият контакт го рарешава. (24 часа)</target> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="Allow message reactions only if your contact allows them." xml:space="preserve"> @@ -689,9 +706,9 @@ <target>Разреши изпращането на изчезващи съобщения.</target> <note>No comment provided by engineer.</note> </trans-unit> - <trans-unit id="Allow to irreversibly delete sent messages." xml:space="preserve"> - <source>Allow to irreversibly delete sent messages.</source> - <target>Позволи необратимо изтриване на изпратените съобщения.</target> + <trans-unit id="Allow to irreversibly delete sent messages. (24 hours)" xml:space="preserve"> + <source>Allow to irreversibly delete sent messages. (24 hours)</source> + <target>Позволи необратимо изтриване на изпратените съобщения. (24 часа)</target> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="Allow to send files and media." xml:space="preserve"> @@ -724,9 +741,9 @@ <target>Позволи на вашите контакти да ви се обаждат.</target> <note>No comment provided by engineer.</note> </trans-unit> - <trans-unit id="Allow your contacts to irreversibly delete sent messages." xml:space="preserve"> - <source>Allow your contacts to irreversibly delete sent messages.</source> - <target>Позволи на вашите контакти да изтриват необратимо изпратените съобщения.</target> + <trans-unit id="Allow your contacts to irreversibly delete sent messages. (24 hours)" xml:space="preserve"> + <source>Allow your contacts to irreversibly delete sent messages. (24 hours)</source> + <target>Позволи на вашите контакти да изтриват необратимо изпратените съобщения. (24 часа)</target> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="Allow your contacts to send disappearing messages." xml:space="preserve"> @@ -746,10 +763,12 @@ </trans-unit> <trans-unit id="Already connecting!" xml:space="preserve"> <source>Already connecting!</source> + <target>В процес на свързване!</target> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="Already joining the group!" xml:space="preserve"> <source>Already joining the group!</source> + <target>Вече се присъединихте към групата!</target> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="Always use relay" xml:space="preserve"> @@ -874,6 +893,7 @@ </trans-unit> <trans-unit id="Bad desktop address" xml:space="preserve"> <source>Bad desktop address</source> + <target>Грешен адрес на настолното устройство</target> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="Bad message ID" xml:space="preserve"> @@ -888,6 +908,7 @@ </trans-unit> <trans-unit id="Better groups" xml:space="preserve"> <source>Better groups</source> + <target>По-добри групи</target> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="Better messages" xml:space="preserve"> @@ -897,18 +918,34 @@ </trans-unit> <trans-unit id="Block" xml:space="preserve"> <source>Block</source> + <target>Блокирай</target> + <note>No comment provided by engineer.</note> + </trans-unit> + <trans-unit id="Block for all" xml:space="preserve"> + <source>Block for all</source> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="Block group members" xml:space="preserve"> <source>Block group members</source> + <target>Блокиране на членове на групата</target> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="Block member" xml:space="preserve"> <source>Block member</source> + <target>Блокирай член</target> + <note>No comment provided by engineer.</note> + </trans-unit> + <trans-unit id="Block member for all?" xml:space="preserve"> + <source>Block member for all?</source> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="Block member?" xml:space="preserve"> <source>Block member?</source> + <target>Блокирай члена?</target> + <note>No comment provided by engineer.</note> + </trans-unit> + <trans-unit id="Blocked by admin" xml:space="preserve"> + <source>Blocked by admin</source> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="Both you and your contact can add message reactions." xml:space="preserve"> @@ -916,9 +953,9 @@ <target>И вие, и вашият контакт можете да добавяте реакции към съобщението.</target> <note>No comment provided by engineer.</note> </trans-unit> - <trans-unit id="Both you and your contact can irreversibly delete sent messages." xml:space="preserve"> - <source>Both you and your contact can irreversibly delete sent messages.</source> - <target>И вие, и вашият контакт можете да изтриете необратимо изпратените съобщения.</target> + <trans-unit id="Both you and your contact can irreversibly delete sent messages. (24 hours)" xml:space="preserve"> + <source>Both you and your contact can irreversibly delete sent messages. (24 hours)</source> + <target>И вие, и вашият контакт можете да изтриете необратимо изпратените съобщения. (24 часа)</target> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="Both you and your contact can make calls." xml:space="preserve"> @@ -956,9 +993,9 @@ <target>Обаждания</target> <note>No comment provided by engineer.</note> </trans-unit> - <trans-unit id="Can't delete user profile!" xml:space="preserve"> - <source>Can't delete user profile!</source> - <target>Потребителският профил не може да се изтрие!</target> + <trans-unit id="Camera not available" xml:space="preserve"> + <source>Camera not available</source> + <target>Камерата е неодстъпна</target> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="Can't invite contact!" xml:space="preserve"> @@ -1072,6 +1109,11 @@ <target>Чатът е спрян</target> <note>No comment provided by engineer.</note> </trans-unit> + <trans-unit id="Chat is stopped. If you already used this database on another device, you should transfer it back before starting chat." xml:space="preserve"> + <source>Chat is stopped. If you already used this database on another device, you should transfer it back before starting chat.</source> + <target>Чатът е спрян. Ако вече сте използвали тази база данни на друго устройство, трябва да я прехвърлите обратно, преди да стартирате чата отново.</target> + <note>No comment provided by engineer.</note> + </trans-unit> <trans-unit id="Chat preferences" xml:space="preserve"> <source>Chat preferences</source> <target>Чат настройки</target> @@ -1117,6 +1159,10 @@ <target>Изчисти разговора?</target> <note>No comment provided by engineer.</note> </trans-unit> + <trans-unit id="Clear private notes?" xml:space="preserve"> + <source>Clear private notes?</source> + <note>No comment provided by engineer.</note> + </trans-unit> <trans-unit id="Clear verification" xml:space="preserve"> <source>Clear verification</source> <target>Изчисти проверката</target> @@ -1174,6 +1220,7 @@ </trans-unit> <trans-unit id="Connect automatically" xml:space="preserve"> <source>Connect automatically</source> + <target>Автоматично свъзрване</target> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="Connect incognito" xml:space="preserve"> @@ -1183,24 +1230,31 @@ </trans-unit> <trans-unit id="Connect to desktop" xml:space="preserve"> <source>Connect to desktop</source> + <target>Свързване с настолно устройство</target> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="Connect to yourself?" xml:space="preserve"> <source>Connect to yourself?</source> + <target>Свърване със себе си?</target> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="Connect to yourself? This is your own SimpleX address!" xml:space="preserve"> <source>Connect to yourself? This is your own SimpleX address!</source> + <target>Свърване със себе си? +Това е вашият личен SimpleX адрес!</target> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="Connect to yourself? This is your own one-time link!" xml:space="preserve"> <source>Connect to yourself? This is your own one-time link!</source> + <target>Свърване със себе си? +Това е вашят еднократен линк за връзка!</target> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="Connect via contact address" xml:space="preserve"> <source>Connect via contact address</source> + <target>Свързване чрез адрес за контакт</target> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="Connect via link" xml:space="preserve"> @@ -1208,11 +1262,6 @@ This is your own one-time link!</source> <target>Свърване чрез линк</target> <note>No comment provided by engineer.</note> </trans-unit> - <trans-unit id="Connect via link / QR code" xml:space="preserve"> - <source>Connect via link / QR code</source> - <target>Свърване чрез линк/QR код</target> - <note>No comment provided by engineer.</note> - </trans-unit> <trans-unit id="Connect via one-time link" xml:space="preserve"> <source>Connect via one-time link</source> <target>Свързване чрез еднократен линк за връзка</target> @@ -1220,14 +1269,17 @@ This is your own one-time link!</source> </trans-unit> <trans-unit id="Connect with %@" xml:space="preserve"> <source>Connect with %@</source> + <target>Свързване с %@</target> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="Connected desktop" xml:space="preserve"> <source>Connected desktop</source> + <target>Свързано настолно устройство</target> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="Connected to desktop" xml:space="preserve"> <source>Connected to desktop</source> + <target>Свързан с настолно устройство</target> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="Connecting server…" xml:space="preserve"> @@ -1242,6 +1294,7 @@ This is your own one-time link!</source> </trans-unit> <trans-unit id="Connecting to desktop" xml:space="preserve"> <source>Connecting to desktop</source> + <target>Свързване с настолно устройство</target> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="Connection" xml:space="preserve"> @@ -1266,6 +1319,7 @@ This is your own one-time link!</source> </trans-unit> <trans-unit id="Connection terminated" xml:space="preserve"> <source>Connection terminated</source> + <target>Връзката е прекратена</target> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="Connection timeout" xml:space="preserve"> @@ -1335,6 +1389,7 @@ This is your own one-time link!</source> </trans-unit> <trans-unit id="Correct name to %@?" xml:space="preserve"> <source>Correct name to %@?</source> + <target>Поправи име на %@?</target> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="Create" xml:space="preserve"> @@ -1349,6 +1404,7 @@ This is your own one-time link!</source> </trans-unit> <trans-unit id="Create a group using a random profile." xml:space="preserve"> <source>Create a group using a random profile.</source> + <target>Създай група с автоматично генериран профилл.</target> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="Create an address to let people connect with you." xml:space="preserve"> @@ -1363,6 +1419,7 @@ This is your own one-time link!</source> </trans-unit> <trans-unit id="Create group" xml:space="preserve"> <source>Create group</source> + <target>Създай група</target> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="Create group link" xml:space="preserve"> @@ -1380,13 +1437,9 @@ This is your own one-time link!</source> <target>Създайте нов профил в [настолното приложение](https://simplex.chat/downloads/). 💻</target> <note>No comment provided by engineer.</note> </trans-unit> - <trans-unit id="Create one-time invitation link" xml:space="preserve"> - <source>Create one-time invitation link</source> - <target>Създай линк за еднократна покана</target> - <note>No comment provided by engineer.</note> - </trans-unit> <trans-unit id="Create profile" xml:space="preserve"> <source>Create profile</source> + <target>Създай профил</target> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="Create queue" xml:space="preserve"> @@ -1404,11 +1457,24 @@ This is your own one-time link!</source> <target>Създай своя профил</target> <note>No comment provided by engineer.</note> </trans-unit> + <trans-unit id="Created at" xml:space="preserve"> + <source>Created at</source> + <note>No comment provided by engineer.</note> + </trans-unit> + <trans-unit id="Created at: %@" xml:space="preserve"> + <source>Created at: %@</source> + <note>copied message info</note> + </trans-unit> <trans-unit id="Created on %@" xml:space="preserve"> <source>Created on %@</source> <target>Създаден на %@</target> <note>No comment provided by engineer.</note> </trans-unit> + <trans-unit id="Creating link…" xml:space="preserve"> + <source>Creating link…</source> + <target>Линкът се създава…</target> + <note>No comment provided by engineer.</note> + </trans-unit> <trans-unit id="Current Passcode" xml:space="preserve"> <source>Current Passcode</source> <target>Текущ kод за достъп</target> @@ -1549,6 +1615,7 @@ This is your own one-time link!</source> </trans-unit> <trans-unit id="Delete %lld messages?" xml:space="preserve"> <source>Delete %lld messages?</source> + <target>Изтриване на %lld съобщения?</target> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="Delete Contact" xml:space="preserve"> @@ -1578,6 +1645,7 @@ This is your own one-time link!</source> </trans-unit> <trans-unit id="Delete and notify contact" xml:space="preserve"> <source>Delete and notify contact</source> + <target>Изтрий и уведоми контакт</target> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="Delete archive" xml:space="preserve"> @@ -1613,6 +1681,8 @@ This is your own one-time link!</source> <trans-unit id="Delete contact? This cannot be undone!" xml:space="preserve"> <source>Delete contact? This cannot be undone!</source> + <target>Изтрий контакт? +Това не може да бъде отменено!</target> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="Delete database" xml:space="preserve"> @@ -1757,14 +1827,17 @@ This cannot be undone!</source> </trans-unit> <trans-unit id="Desktop address" xml:space="preserve"> <source>Desktop address</source> + <target>Адрес на настолно устройство</target> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="Desktop app version %@ is not compatible with this app." xml:space="preserve"> <source>Desktop app version %@ is not compatible with this app.</source> + <target>Версията на настолното приложение %@ не е съвместима с това приложение.</target> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="Desktop devices" xml:space="preserve"> <source>Desktop devices</source> + <target>Настолни устройства</target> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="Develop" xml:space="preserve"> @@ -1859,6 +1932,7 @@ This cannot be undone!</source> </trans-unit> <trans-unit id="Disconnect desktop?" xml:space="preserve"> <source>Disconnect desktop?</source> + <target>Прекъсни връзката с настолното устройство?</target> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="Discover and join groups" xml:space="preserve"> @@ -1868,6 +1942,7 @@ This cannot be undone!</source> </trans-unit> <trans-unit id="Discover via local network" xml:space="preserve"> <source>Discover via local network</source> + <target>Открий през локалната мрежа</target> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="Do NOT use SimpleX for emergency calls." xml:space="preserve"> @@ -1880,6 +1955,11 @@ This cannot be undone!</source> <target>Отложи</target> <note>No comment provided by engineer.</note> </trans-unit> + <trans-unit id="Do not send history to new members." xml:space="preserve"> + <source>Do not send history to new members.</source> + <target>Не изпращай история на нови членове.</target> + <note>No comment provided by engineer.</note> + </trans-unit> <trans-unit id="Don't create address" xml:space="preserve"> <source>Don't create address</source> <target>Не създавай адрес</target> @@ -1907,7 +1987,7 @@ This cannot be undone!</source> </trans-unit> <trans-unit id="Duplicate display name!" xml:space="preserve"> <source>Duplicate display name!</source> - <target>Дублирано показвано име!</target> + <target>Дублирано име!</target> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="Duration" xml:space="preserve"> @@ -1950,6 +2030,11 @@ This cannot be undone!</source> <target>Активиране на автоматично изтриване на съобщения?</target> <note>No comment provided by engineer.</note> </trans-unit> + <trans-unit id="Enable camera access" xml:space="preserve"> + <source>Enable camera access</source> + <target>Разреши достъпа до камерата</target> + <note>No comment provided by engineer.</note> + </trans-unit> <trans-unit id="Enable for all" xml:space="preserve"> <source>Enable for all</source> <target>Активиране за всички</target> @@ -2015,6 +2100,11 @@ This cannot be undone!</source> <target>Криптирано съобщение или друго събитие</target> <note>notification</note> </trans-unit> + <trans-unit id="Encrypted message: app is stopped" xml:space="preserve"> + <source>Encrypted message: app is stopped</source> + <target>Криптирано съобщение: приложението е спряно</target> + <note>notification</note> + </trans-unit> <trans-unit id="Encrypted message: database error" xml:space="preserve"> <source>Encrypted message: database error</source> <target>Криптирано съобщение: грешка в базата данни</target> @@ -2042,10 +2132,12 @@ This cannot be undone!</source> </trans-unit> <trans-unit id="Encryption re-negotiation error" xml:space="preserve"> <source>Encryption re-negotiation error</source> + <target>Грешка при повторно договаряне на криптиране</target> <note>message decrypt error item</note> </trans-unit> <trans-unit id="Encryption re-negotiation failed." xml:space="preserve"> <source>Encryption re-negotiation failed.</source> + <target>Неуспешно повторно договаряне на криптирането.</target> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="Enter Passcode" xml:space="preserve"> @@ -2060,6 +2152,7 @@ This cannot be undone!</source> </trans-unit> <trans-unit id="Enter group name…" xml:space="preserve"> <source>Enter group name…</source> + <target>Въведи име на групата…</target> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="Enter passphrase…" xml:space="preserve"> @@ -2079,6 +2172,7 @@ This cannot be undone!</source> </trans-unit> <trans-unit id="Enter this device name…" xml:space="preserve"> <source>Enter this device name…</source> + <target>Въведи името на това устройство…</target> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="Enter welcome message…" xml:space="preserve"> @@ -2093,6 +2187,7 @@ This cannot be undone!</source> </trans-unit> <trans-unit id="Enter your name…" xml:space="preserve"> <source>Enter your name…</source> + <target>Въведи своето име…</target> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="Error" xml:space="preserve"> @@ -2155,6 +2250,10 @@ This cannot be undone!</source> <target>Грешка при създаване на контакт с член</target> <note>No comment provided by engineer.</note> </trans-unit> + <trans-unit id="Error creating message" xml:space="preserve"> + <source>Error creating message</source> + <note>No comment provided by engineer.</note> + </trans-unit> <trans-unit id="Error creating profile!" xml:space="preserve"> <source>Error creating profile!</source> <target>Грешка при създаване на профил!</target> @@ -2240,6 +2339,11 @@ This cannot be undone!</source> <target>Грешка при зареждане на %@ сървъри</target> <note>No comment provided by engineer.</note> </trans-unit> + <trans-unit id="Error opening chat" xml:space="preserve"> + <source>Error opening chat</source> + <target>Грешка при отваряне на чата</target> + <note>No comment provided by engineer.</note> + </trans-unit> <trans-unit id="Error receiving file" xml:space="preserve"> <source>Error receiving file</source> <target>Грешка при получаване на файл</target> @@ -2280,6 +2384,11 @@ This cannot be undone!</source> <target>Грешка при запазване на потребителска парола</target> <note>No comment provided by engineer.</note> </trans-unit> + <trans-unit id="Error scanning code: %@" xml:space="preserve"> + <source>Error scanning code: %@</source> + <target>Грешка при сканиране на кода: %@</target> + <note>No comment provided by engineer.</note> + </trans-unit> <trans-unit id="Error sending email" xml:space="preserve"> <source>Error sending email</source> <target>Грешка при изпращане на имейл</target> @@ -2372,6 +2481,7 @@ This cannot be undone!</source> </trans-unit> <trans-unit id="Expand" xml:space="preserve"> <source>Expand</source> + <target>Разшири</target> <note>chat item action</note> </trans-unit> <trans-unit id="Export database" xml:space="preserve"> @@ -2406,6 +2516,7 @@ This cannot be undone!</source> </trans-unit> <trans-unit id="Faster joining and more reliable messages." xml:space="preserve"> <source>Faster joining and more reliable messages.</source> + <target>По-бързо присъединяване и по-надеждни съобщения.</target> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="Favorite" xml:space="preserve"> @@ -2505,6 +2616,7 @@ This cannot be undone!</source> </trans-unit> <trans-unit id="Found desktop" xml:space="preserve"> <source>Found desktop</source> + <target>Намерено настолно устройство</target> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="French interface" xml:space="preserve"> @@ -2529,6 +2641,7 @@ This cannot be undone!</source> </trans-unit> <trans-unit id="Fully decentralized – visible only to members." xml:space="preserve"> <source>Fully decentralized – visible only to members.</source> + <target>Напълно децентрализирана – видима е само за членовете.</target> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="Fully re-implemented - work in background!" xml:space="preserve"> @@ -2553,15 +2666,17 @@ This cannot be undone!</source> </trans-unit> <trans-unit id="Group already exists" xml:space="preserve"> <source>Group already exists</source> + <target>Групата вече съществува</target> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="Group already exists!" xml:space="preserve"> <source>Group already exists!</source> + <target>Групата вече съществува!</target> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="Group display name" xml:space="preserve"> <source>Group display name</source> - <target>Показвано име на групата</target> + <target>Име на групата</target> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="Group full name (optional)" xml:space="preserve"> @@ -2604,9 +2719,9 @@ This cannot be undone!</source> <target>Членовете на групата могат да добавят реакции към съобщенията.</target> <note>No comment provided by engineer.</note> </trans-unit> - <trans-unit id="Group members can irreversibly delete sent messages." xml:space="preserve"> - <source>Group members can irreversibly delete sent messages.</source> - <target>Членовете на групата могат необратимо да изтриват изпратените съобщения.</target> + <trans-unit id="Group members can irreversibly delete sent messages. (24 hours)" xml:space="preserve"> + <source>Group members can irreversibly delete sent messages. (24 hours)</source> + <target>Членовете на групата могат необратимо да изтриват изпратените съобщения. (24 часа)</target> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="Group members can send direct messages." xml:space="preserve"> @@ -2714,6 +2829,11 @@ This cannot be undone!</source> <target>История</target> <note>No comment provided by engineer.</note> </trans-unit> + <trans-unit id="History is not sent to new members." xml:space="preserve"> + <source>History is not sent to new members.</source> + <target>Историята не се изпраща на нови членове.</target> + <note>No comment provided by engineer.</note> + </trans-unit> <trans-unit id="How SimpleX works" xml:space="preserve"> <source>How SimpleX works</source> <target>Как работи SimpleX</target> @@ -2749,11 +2869,6 @@ This cannot be undone!</source> <target>Ако не можете да се срещнете лично, покажете QR код във видеоразговора или споделете линка.</target> <note>No comment provided by engineer.</note> </trans-unit> - <trans-unit id="If you cannot meet in person, you can **scan QR code in the video call**, or your contact can share an invitation link." xml:space="preserve"> - <source>If you cannot meet in person, you can **scan QR code in the video call**, or your contact can share an invitation link.</source> - <target>Ако не можете да се срещнете на живо, можете да **сканирате QR код във видеообаждането** или вашият контакт може да сподели линк за покана.</target> - <note>No comment provided by engineer.</note> - </trans-unit> <trans-unit id="If you enter this passcode when opening the app, all app data will be irreversibly removed!" xml:space="preserve"> <source>If you enter this passcode when opening the app, all app data will be irreversibly removed!</source> <target>Ако въведете този kод за достъп, когато отваряте приложението, всички данни от приложението ще бъдат необратимо изтрити!</target> @@ -2809,6 +2924,10 @@ This cannot be undone!</source> <target>Импортиране на база данни</target> <note>No comment provided by engineer.</note> </trans-unit> + <trans-unit id="Improved message delivery" xml:space="preserve"> + <source>Improved message delivery</source> + <note>No comment provided by engineer.</note> + </trans-unit> <trans-unit id="Improved privacy and security" xml:space="preserve"> <source>Improved privacy and security</source> <target>Подобрена поверителност и сигурност</target> @@ -2831,6 +2950,7 @@ This cannot be undone!</source> </trans-unit> <trans-unit id="Incognito groups" xml:space="preserve"> <source>Incognito groups</source> + <target>Инкогнито групи</target> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="Incognito mode" xml:space="preserve"> @@ -2865,6 +2985,7 @@ This cannot be undone!</source> </trans-unit> <trans-unit id="Incompatible version" xml:space="preserve"> <source>Incompatible version</source> + <target>Несъвместима версия</target> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="Incorrect passcode" xml:space="preserve"> @@ -2909,13 +3030,34 @@ This cannot be undone!</source> <target>Интерфейс</target> <note>No comment provided by engineer.</note> </trans-unit> + <trans-unit id="Invalid QR code" xml:space="preserve"> + <source>Invalid QR code</source> + <target>Невалиден QR код</target> + <note>No comment provided by engineer.</note> + </trans-unit> <trans-unit id="Invalid connection link" xml:space="preserve"> <source>Invalid connection link</source> <target>Невалиден линк за връзка</target> <note>No comment provided by engineer.</note> </trans-unit> + <trans-unit id="Invalid display name!" xml:space="preserve"> + <source>Invalid display name!</source> + <target>Невалидно име!</target> + <note>No comment provided by engineer.</note> + </trans-unit> + <trans-unit id="Invalid link" xml:space="preserve"> + <source>Invalid link</source> + <target>Невалиден линк</target> + <note>No comment provided by engineer.</note> + </trans-unit> <trans-unit id="Invalid name!" xml:space="preserve"> <source>Invalid name!</source> + <target>Невалидно име!</target> + <note>No comment provided by engineer.</note> + </trans-unit> + <trans-unit id="Invalid response" xml:space="preserve"> + <source>Invalid response</source> + <target>Невалиден отговор</target> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="Invalid server address!" xml:space="preserve"> @@ -3009,8 +3151,13 @@ This cannot be undone!</source> <target>Влез в групата</target> <note>No comment provided by engineer.</note> </trans-unit> + <trans-unit id="Join group conversations" xml:space="preserve"> + <source>Join group conversations</source> + <note>No comment provided by engineer.</note> + </trans-unit> <trans-unit id="Join group?" xml:space="preserve"> <source>Join group?</source> + <target>Влез в групата?</target> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="Join incognito" xml:space="preserve"> @@ -3020,11 +3167,14 @@ This cannot be undone!</source> </trans-unit> <trans-unit id="Join with current profile" xml:space="preserve"> <source>Join with current profile</source> + <target>Присъединяване с текущия профил</target> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="Join your group? This is your link for group %@!" xml:space="preserve"> <source>Join your group? This is your link for group %@!</source> + <target>Влез в твоята група? +Това е вашят линк за група %@!</target> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="Joining group" xml:space="preserve"> @@ -3032,8 +3182,19 @@ This is your link for group %@!</source> <target>Присъединяване към групата</target> <note>No comment provided by engineer.</note> </trans-unit> + <trans-unit id="Keep" xml:space="preserve"> + <source>Keep</source> + <target>Запази</target> + <note>No comment provided by engineer.</note> + </trans-unit> <trans-unit id="Keep the app open to use it from desktop" xml:space="preserve"> <source>Keep the app open to use it from desktop</source> + <target>Дръжте приложението отворено, за да го използвате от настолното устройство</target> + <note>No comment provided by engineer.</note> + </trans-unit> + <trans-unit id="Keep unused invitation?" xml:space="preserve"> + <source>Keep unused invitation?</source> + <target>Запази неизползваната покана за връзка?</target> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="Keep your connections" xml:space="preserve"> @@ -3098,14 +3259,17 @@ This is your link for group %@!</source> </trans-unit> <trans-unit id="Link mobile and desktop apps! 🔗" xml:space="preserve"> <source>Link mobile and desktop apps! 🔗</source> + <target>Свържете мобилни и настолни приложения! 🔗</target> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="Linked desktop options" xml:space="preserve"> <source>Linked desktop options</source> + <target>Настройки на запомнени настолни устройства</target> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="Linked desktops" xml:space="preserve"> <source>Linked desktops</source> + <target>Запомнени настолни устройства</target> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="Live message!" xml:space="preserve"> @@ -3118,6 +3282,11 @@ This is your link for group %@!</source> <target>Съобщения на живо</target> <note>No comment provided by engineer.</note> </trans-unit> + <trans-unit id="Local" xml:space="preserve"> + <source>Local</source> + <target>Локално</target> + <note>No comment provided by engineer.</note> + </trans-unit> <trans-unit id="Local name" xml:space="preserve"> <source>Local name</source> <target>Локално име</target> @@ -3260,6 +3429,7 @@ This is your link for group %@!</source> </trans-unit> <trans-unit id="Messages from %@ will be shown!" xml:space="preserve"> <source>Messages from %@ will be shown!</source> + <target>Съобщенията от %@ ще бъдат показани!</target> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="Migrating database archive…" xml:space="preserve"> @@ -3357,6 +3527,11 @@ This is your link for group %@!</source> <target>Нов kод за достъп</target> <note>No comment provided by engineer.</note> </trans-unit> + <trans-unit id="New chat" xml:space="preserve"> + <source>New chat</source> + <target>Нов чат</target> + <note>No comment provided by engineer.</note> + </trans-unit> <trans-unit id="New contact request" xml:space="preserve"> <source>New contact request</source> <target>Нова заявка за контакт</target> @@ -3379,7 +3554,7 @@ This is your link for group %@!</source> </trans-unit> <trans-unit id="New display name" xml:space="preserve"> <source>New display name</source> - <target>Ново показвано име</target> + <target>Ново име</target> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="New in %@" xml:space="preserve"> @@ -3459,6 +3634,7 @@ This is your link for group %@!</source> </trans-unit> <trans-unit id="Not compatible!" xml:space="preserve"> <source>Not compatible!</source> + <target>Несъвместим!</target> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="Notifications" xml:space="preserve"> @@ -3480,16 +3656,16 @@ This is your link for group %@!</source> - да деактивират членове (роля "наблюдател")</target> <note>No comment provided by engineer.</note> </trans-unit> + <trans-unit id="OK" xml:space="preserve"> + <source>OK</source> + <target>ОК</target> + <note>No comment provided by engineer.</note> + </trans-unit> <trans-unit id="Off" xml:space="preserve"> <source>Off</source> <target>Изключено</target> <note>No comment provided by engineer.</note> </trans-unit> - <trans-unit id="Off (Local)" xml:space="preserve"> - <source>Off (Local)</source> - <target>Изключено (Локално)</target> - <note>No comment provided by engineer.</note> - </trans-unit> <trans-unit id="Ok" xml:space="preserve"> <source>Ok</source> <target>Ок</target> @@ -3550,9 +3726,9 @@ This is your link for group %@!</source> <target>Само вие можете да добавяте реакции на съобщенията.</target> <note>No comment provided by engineer.</note> </trans-unit> - <trans-unit id="Only you can irreversibly delete messages (your contact can mark them for deletion)." xml:space="preserve"> - <source>Only you can irreversibly delete messages (your contact can mark them for deletion).</source> - <target>Само вие можете необратимо да изтриете съобщения (вашият контакт може да ги маркира за изтриване).</target> + <trans-unit id="Only you can irreversibly delete messages (your contact can mark them for deletion). (24 hours)" xml:space="preserve"> + <source>Only you can irreversibly delete messages (your contact can mark them for deletion). (24 hours)</source> + <target>Само вие можете необратимо да изтриете съобщения (вашият контакт може да ги маркира за изтриване). (24 часа)</target> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="Only you can make calls." xml:space="preserve"> @@ -3575,9 +3751,9 @@ This is your link for group %@!</source> <target>Само вашият контакт може да добавя реакции на съобщенията.</target> <note>No comment provided by engineer.</note> </trans-unit> - <trans-unit id="Only your contact can irreversibly delete messages (you can mark them for deletion)." xml:space="preserve"> - <source>Only your contact can irreversibly delete messages (you can mark them for deletion).</source> - <target>Само вашият контакт може необратимо да изтрие съобщения (можете да ги маркирате за изтриване).</target> + <trans-unit id="Only your contact can irreversibly delete messages (you can mark them for deletion). (24 hours)" xml:space="preserve"> + <source>Only your contact can irreversibly delete messages (you can mark them for deletion). (24 hours)</source> + <target>Само вашият контакт може необратимо да изтрие съобщения (можете да ги маркирате за изтриване). (24 часа)</target> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="Only your contact can make calls." xml:space="preserve"> @@ -3617,6 +3793,7 @@ This is your link for group %@!</source> </trans-unit> <trans-unit id="Open group" xml:space="preserve"> <source>Open group</source> + <target>Отвори група</target> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="Open user profiles" xml:space="preserve"> @@ -3629,9 +3806,19 @@ This is your link for group %@!</source> <target>Протокол и код с отворен код – всеки може да оперира собствени сървъри.</target> <note>No comment provided by engineer.</note> </trans-unit> - <trans-unit id="Opening database…" xml:space="preserve"> - <source>Opening database…</source> - <target>Отваряне на база данни…</target> + <trans-unit id="Opening app…" xml:space="preserve"> + <source>Opening app…</source> + <target>Приложението се отваря…</target> + <note>No comment provided by engineer.</note> + </trans-unit> + <trans-unit id="Or scan QR code" xml:space="preserve"> + <source>Or scan QR code</source> + <target>Или сканирай QR код</target> + <note>No comment provided by engineer.</note> + </trans-unit> + <trans-unit id="Or show this code" xml:space="preserve"> + <source>Or show this code</source> + <target>Или покажи този код</target> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="PING count" xml:space="preserve"> @@ -3674,13 +3861,13 @@ This is your link for group %@!</source> <target>Парола за показване</target> <note>No comment provided by engineer.</note> </trans-unit> - <trans-unit id="Paste" xml:space="preserve"> - <source>Paste</source> - <target>Постави</target> - <note>No comment provided by engineer.</note> + <trans-unit id="Past member %@" xml:space="preserve"> + <source>Past member %@</source> + <note>past/unknown group member</note> </trans-unit> <trans-unit id="Paste desktop address" xml:space="preserve"> <source>Paste desktop address</source> + <target>Постави адрес на настолно устройство</target> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="Paste image" xml:space="preserve"> @@ -3688,15 +3875,14 @@ This is your link for group %@!</source> <target>Постави изображение</target> <note>No comment provided by engineer.</note> </trans-unit> - <trans-unit id="Paste received link" xml:space="preserve"> - <source>Paste received link</source> - <target>Постави получения линк</target> + <trans-unit id="Paste link to connect!" xml:space="preserve"> + <source>Paste link to connect!</source> <note>No comment provided by engineer.</note> </trans-unit> - <trans-unit id="Paste the link you received to connect with your contact." xml:space="preserve"> - <source>Paste the link you received to connect with your contact.</source> - <target>Поставете линка, който сте получили, за да се свържете с вашия контакт.</target> - <note>placeholder</note> + <trans-unit id="Paste the link you received" xml:space="preserve"> + <source>Paste the link you received</source> + <target>Постави получения линк</target> + <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="People can connect to you only via the links you share." xml:space="preserve"> <source>People can connect to you only via the links you share.</source> @@ -3733,6 +3919,13 @@ This is your link for group %@!</source> <target>Моля, проверете вашите настройки и тези вашия за контакт.</target> <note>No comment provided by engineer.</note> </trans-unit> + <trans-unit id="Please contact developers. Error: %@" xml:space="preserve"> + <source>Please contact developers. +Error: %@</source> + <target>Моля, свържете се с разработчиците. +Грешка: %@</target> + <note>No comment provided by engineer.</note> + </trans-unit> <trans-unit id="Please contact group admin." xml:space="preserve"> <source>Please contact group admin.</source> <target>Моля, свържете се с груповия администартор.</target> @@ -3818,6 +4011,10 @@ This is your link for group %@!</source> <target>Поверителни имена на файлове</target> <note>No comment provided by engineer.</note> </trans-unit> + <trans-unit id="Private notes" xml:space="preserve"> + <source>Private notes</source> + <note>name of notes to self</note> + </trans-unit> <trans-unit id="Profile and server connections" xml:space="preserve"> <source>Profile and server connections</source> <target>Профилни и сървърни връзки</target> @@ -3830,10 +4027,12 @@ This is your link for group %@!</source> </trans-unit> <trans-unit id="Profile name" xml:space="preserve"> <source>Profile name</source> + <target>Име на профила</target> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="Profile name:" xml:space="preserve"> <source>Profile name:</source> + <target>Име на профила:</target> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="Profile password" xml:space="preserve"> @@ -3936,6 +4135,11 @@ This is your link for group %@!</source> <target>Прочетете повече в [Ръководство за потребителя](https://simplex.chat/docs/guide/app-settings.html#your-simplex-contact-address).</target> <note>No comment provided by engineer.</note> </trans-unit> + <trans-unit id="Read more in [User Guide](https://simplex.chat/docs/guide/chat-profiles.html#incognito-mode)." xml:space="preserve"> + <source>Read more in [User Guide](https://simplex.chat/docs/guide/chat-profiles.html#incognito-mode).</source> + <target>Прочетете повече в [Ръководство за потребителя](https://simplex.chat/docs/guide/chat-profiles.html#incognito-mode).</target> + <note>No comment provided by engineer.</note> + </trans-unit> <trans-unit id="Read more in [User Guide](https://simplex.chat/docs/guide/readme.html#connect-to-friends)." xml:space="preserve"> <source>Read more in [User Guide](https://simplex.chat/docs/guide/readme.html#connect-to-friends).</source> <target>Прочетете повече в [Ръководство на потребителя](https://simplex.chat/docs/guide/readme.html#connect-to-friends).</target> @@ -3991,6 +4195,10 @@ This is your link for group %@!</source> <target>Получаване чрез</target> <note>No comment provided by engineer.</note> </trans-unit> + <trans-unit id="Recent history and improved [directory bot](simplex:/contact#/?v=1-4&smp=smp%3A%2F%2Fu2dS9sG8nMNURyZwqASV4yROM28Er0luVTx5X1CsMrU%3D%40smp4.simplex.im%2FeXSPwqTkKyDO3px4fLf1wx3MvPdjdLW3%23%2F%3Fv%3D1-2%26dh%3DMCowBQYDK2VuAyEAaiv6MkMH44L2TcYrt_CsX3ZvM11WgbMEUn0hkIKTOho%253D%26srv%3Do5vmywmrnaxalvz6wi3zicyftgio6psuvyniis6gco6bp6ekl4cqj4id.onion)." xml:space="preserve"> + <source>Recent history and improved [directory bot](simplex:/contact#/?v=1-4&smp=smp%3A%2F%2Fu2dS9sG8nMNURyZwqASV4yROM28Er0luVTx5X1CsMrU%3D%40smp4.simplex.im%2FeXSPwqTkKyDO3px4fLf1wx3MvPdjdLW3%23%2F%3Fv%3D1-2%26dh%3DMCowBQYDK2VuAyEAaiv6MkMH44L2TcYrt_CsX3ZvM11WgbMEUn0hkIKTOho%253D%26srv%3Do5vmywmrnaxalvz6wi3zicyftgio6psuvyniis6gco6bp6ekl4cqj4id.onion).</source> + <note>No comment provided by engineer.</note> + </trans-unit> <trans-unit id="Recipients see updates as you type them." xml:space="preserve"> <source>Recipients see updates as you type them.</source> <target>Получателите виждат актуализации, докато ги въвеждате.</target> @@ -4083,10 +4291,12 @@ This is your link for group %@!</source> </trans-unit> <trans-unit id="Repeat connection request?" xml:space="preserve"> <source>Repeat connection request?</source> + <target>Изпрати отново заявката за свързване?</target> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="Repeat join request?" xml:space="preserve"> <source>Repeat join request?</source> + <target>Изпрати отново заявката за присъединяване?</target> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="Reply" xml:space="preserve"> @@ -4144,6 +4354,11 @@ This is your link for group %@!</source> <target>Грешка при възстановяване на базата данни</target> <note>No comment provided by engineer.</note> </trans-unit> + <trans-unit id="Retry" xml:space="preserve"> + <source>Retry</source> + <target>Опитай отново</target> + <note>No comment provided by engineer.</note> + </trans-unit> <trans-unit id="Reveal" xml:space="preserve"> <source>Reveal</source> <target>Покажи</target> @@ -4269,6 +4484,10 @@ This is your link for group %@!</source> <target>Запазените WebRTC ICE сървъри ще бъдат премахнати</target> <note>No comment provided by engineer.</note> </trans-unit> + <trans-unit id="Saved message" xml:space="preserve"> + <source>Saved message</source> + <note>message info title</note> + </trans-unit> <trans-unit id="Scan QR code" xml:space="preserve"> <source>Scan QR code</source> <target>Сканирай QR код</target> @@ -4276,6 +4495,7 @@ This is your link for group %@!</source> </trans-unit> <trans-unit id="Scan QR code from desktop" xml:space="preserve"> <source>Scan QR code from desktop</source> + <target>Сканирай QR код от настолното устройство</target> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="Scan code" xml:space="preserve"> @@ -4298,6 +4518,15 @@ This is your link for group %@!</source> <target>Търсене</target> <note>No comment provided by engineer.</note> </trans-unit> + <trans-unit id="Search bar accepts invitation links." xml:space="preserve"> + <source>Search bar accepts invitation links.</source> + <note>No comment provided by engineer.</note> + </trans-unit> + <trans-unit id="Search or paste SimpleX link" xml:space="preserve"> + <source>Search or paste SimpleX link</source> + <target>Търсене или поставяне на SimpleX линк</target> + <note>No comment provided by engineer.</note> + </trans-unit> <trans-unit id="Secure queue" xml:space="preserve"> <source>Secure queue</source> <target>Сигурна опашка</target> @@ -4403,6 +4632,11 @@ This is your link for group %@!</source> <target>Изпрати от галерия или персонализирани клавиатури.</target> <note>No comment provided by engineer.</note> </trans-unit> + <trans-unit id="Send up to 100 last messages to new members." xml:space="preserve"> + <source>Send up to 100 last messages to new members.</source> + <target>Изпращане до последните 100 съобщения на нови членове.</target> + <note>No comment provided by engineer.</note> + </trans-unit> <trans-unit id="Sender cancelled file transfer." xml:space="preserve"> <source>Sender cancelled file transfer.</source> <target>Подателят отмени прехвърлянето на файла.</target> @@ -4500,6 +4734,7 @@ This is your link for group %@!</source> </trans-unit> <trans-unit id="Session code" xml:space="preserve"> <source>Session code</source> + <target>Код на сесията</target> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="Set 1 day" xml:space="preserve"> @@ -4572,9 +4807,9 @@ This is your link for group %@!</source> <target>Сподели линк</target> <note>No comment provided by engineer.</note> </trans-unit> - <trans-unit id="Share one-time invitation link" xml:space="preserve"> - <source>Share one-time invitation link</source> - <target>Сподели линк за еднократна покана</target> + <trans-unit id="Share this 1-time invite link" xml:space="preserve"> + <source>Share this 1-time invite link</source> + <target>Сподели този еднократен линк за връзка</target> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="Share with contacts" xml:space="preserve"> @@ -4697,16 +4932,16 @@ This is your link for group %@!</source> <target>Някой</target> <note>notification title</note> </trans-unit> - <trans-unit id="Start a new chat" xml:space="preserve"> - <source>Start a new chat</source> - <target>Започни нов чат</target> - <note>No comment provided by engineer.</note> - </trans-unit> <trans-unit id="Start chat" xml:space="preserve"> <source>Start chat</source> <target>Започни чат</target> <note>No comment provided by engineer.</note> </trans-unit> + <trans-unit id="Start chat?" xml:space="preserve"> + <source>Start chat?</source> + <target>Стартирай чата?</target> + <note>No comment provided by engineer.</note> + </trans-unit> <trans-unit id="Start migration" xml:space="preserve"> <source>Start migration</source> <target>Започни миграция</target> @@ -4814,6 +5049,7 @@ This is your link for group %@!</source> </trans-unit> <trans-unit id="Tap to Connect" xml:space="preserve"> <source>Tap to Connect</source> + <target>Докосни за свързване</target> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="Tap to activate profile." xml:space="preserve"> @@ -4831,6 +5067,16 @@ This is your link for group %@!</source> <target>Докосни за инкогнито вход</target> <note>No comment provided by engineer.</note> </trans-unit> + <trans-unit id="Tap to paste link" xml:space="preserve"> + <source>Tap to paste link</source> + <target>Докосни за поставяне на линк за връзка</target> + <note>No comment provided by engineer.</note> + </trans-unit> + <trans-unit id="Tap to scan" xml:space="preserve"> + <source>Tap to scan</source> + <target>Докосни за сканиране</target> + <note>No comment provided by engineer.</note> + </trans-unit> <trans-unit id="Tap to start a new chat" xml:space="preserve"> <source>Tap to start a new chat</source> <target>Докосни за започване на нов чат</target> @@ -4893,6 +5139,11 @@ It can happen because of some bug or when the connection is compromised.</source <target>Опитът за промяна на паролата на базата данни не беше завършен.</target> <note>No comment provided by engineer.</note> </trans-unit> + <trans-unit id="The code you scanned is not a SimpleX link QR code." xml:space="preserve"> + <source>The code you scanned is not a SimpleX link QR code.</source> + <target>QR кодът, който сканирахте, не е SimpleX линк за връзка.</target> + <note>No comment provided by engineer.</note> + </trans-unit> <trans-unit id="The connection you accepted will be cancelled!" xml:space="preserve"> <source>The connection you accepted will be cancelled!</source> <target>Връзката, която приехте, ще бъде отказана!</target> @@ -4958,21 +5209,16 @@ It can happen because of some bug or when the connection is compromised.</source <target>Сървърите за нови връзки на текущия ви чат профил **%@**.</target> <note>No comment provided by engineer.</note> </trans-unit> + <trans-unit id="The text you pasted is not a SimpleX link." xml:space="preserve"> + <source>The text you pasted is not a SimpleX link.</source> + <target>Текстът, който поставихте, не е SimpleX линк за връзка.</target> + <note>No comment provided by engineer.</note> + </trans-unit> <trans-unit id="Theme" xml:space="preserve"> <source>Theme</source> <target>Тема</target> <note>No comment provided by engineer.</note> </trans-unit> - <trans-unit id="There should be at least one user profile." xml:space="preserve"> - <source>There should be at least one user profile.</source> - <target>Трябва да има поне един потребителски профил.</target> - <note>No comment provided by engineer.</note> - </trans-unit> - <trans-unit id="There should be at least one visible user profile." xml:space="preserve"> - <source>There should be at least one visible user profile.</source> - <target>Трябва да има поне един видим потребителски профил.</target> - <note>No comment provided by engineer.</note> - </trans-unit> <trans-unit id="These settings are for your current profile **%@**." xml:space="preserve"> <source>These settings are for your current profile **%@**.</source> <target>Тези настройки са за текущия ви профил **%@**.</target> @@ -5000,6 +5246,12 @@ It can happen because of some bug or when the connection is compromised.</source </trans-unit> <trans-unit id="This device name" xml:space="preserve"> <source>This device name</source> + <target>Името на това устройство</target> + <note>No comment provided by engineer.</note> + </trans-unit> + <trans-unit id="This display name is invalid. Please choose another name." xml:space="preserve"> + <source>This display name is invalid. Please choose another name.</source> + <target>Това име е невалидно. Моля, изберете друго име.</target> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="This group has over %lld members, delivery receipts are not sent." xml:space="preserve"> @@ -5014,10 +5266,12 @@ It can happen because of some bug or when the connection is compromised.</source </trans-unit> <trans-unit id="This is your own SimpleX address!" xml:space="preserve"> <source>This is your own SimpleX address!</source> + <target>Това е вашият личен SimpleX адрес!</target> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="This is your own one-time link!" xml:space="preserve"> <source>This is your own one-time link!</source> + <target>Това е вашят еднократен линк за връзка!</target> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="This setting applies to messages in your current chat profile **%@**." xml:space="preserve"> @@ -5037,6 +5291,7 @@ It can happen because of some bug or when the connection is compromised.</source </trans-unit> <trans-unit id="To hide unwanted messages." xml:space="preserve"> <source>To hide unwanted messages.</source> + <target>Скриване на нежелани съобщения.</target> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="To make a new connection" xml:space="preserve"> @@ -5101,16 +5356,15 @@ You will be prompted to complete authentication before this feature is enabled.< <target>Опит за свързване със сървъра, използван за получаване на съобщения от този контакт.</target> <note>No comment provided by engineer.</note> </trans-unit> + <trans-unit id="Turkish interface" xml:space="preserve"> + <source>Turkish interface</source> + <note>No comment provided by engineer.</note> + </trans-unit> <trans-unit id="Turn off" xml:space="preserve"> <source>Turn off</source> <target>Изключи</target> <note>No comment provided by engineer.</note> </trans-unit> - <trans-unit id="Turn off notifications?" xml:space="preserve"> - <source>Turn off notifications?</source> - <target>Изключи известията?</target> - <note>No comment provided by engineer.</note> - </trans-unit> <trans-unit id="Turn on" xml:space="preserve"> <source>Turn on</source> <target>Включи</target> @@ -5123,14 +5377,25 @@ You will be prompted to complete authentication before this feature is enabled.< </trans-unit> <trans-unit id="Unblock" xml:space="preserve"> <source>Unblock</source> + <target>Отблокирай</target> + <note>No comment provided by engineer.</note> + </trans-unit> + <trans-unit id="Unblock for all" xml:space="preserve"> + <source>Unblock for all</source> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="Unblock member" xml:space="preserve"> <source>Unblock member</source> + <target>Отблокирай член</target> + <note>No comment provided by engineer.</note> + </trans-unit> + <trans-unit id="Unblock member for all?" xml:space="preserve"> + <source>Unblock member for all?</source> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="Unblock member?" xml:space="preserve"> <source>Unblock member?</source> + <target>Отблокирай член?</target> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="Unexpected error: %@" xml:space="preserve"> @@ -5197,10 +5462,12 @@ To connect, please ask your contact to create another connection link and check </trans-unit> <trans-unit id="Unlink" xml:space="preserve"> <source>Unlink</source> + <target>Забрави</target> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="Unlink desktop?" xml:space="preserve"> <source>Unlink desktop?</source> + <target>Забрави настолно устройство?</target> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="Unlock" xml:space="preserve"> @@ -5223,6 +5490,11 @@ To connect, please ask your contact to create another connection link and check <target>Непрочетено</target> <note>No comment provided by engineer.</note> </trans-unit> + <trans-unit id="Up to 100 last messages are sent to new members." xml:space="preserve"> + <source>Up to 100 last messages are sent to new members.</source> + <target>На новите членове се изпращат до последните 100 съобщения.</target> + <note>No comment provided by engineer.</note> + </trans-unit> <trans-unit id="Update" xml:space="preserve"> <source>Update</source> <target>Актуализация</target> @@ -5295,6 +5567,7 @@ To connect, please ask your contact to create another connection link and check </trans-unit> <trans-unit id="Use from desktop" xml:space="preserve"> <source>Use from desktop</source> + <target>Използвай от настолно устройство</target> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="Use iOS call interface" xml:space="preserve"> @@ -5307,6 +5580,11 @@ To connect, please ask your contact to create another connection link and check <target>Използвай нов инкогнито профил</target> <note>No comment provided by engineer.</note> </trans-unit> + <trans-unit id="Use only local notifications?" xml:space="preserve"> + <source>Use only local notifications?</source> + <target>Използвай само локални известия?</target> + <note>No comment provided by engineer.</note> + </trans-unit> <trans-unit id="Use server" xml:space="preserve"> <source>Use server</source> <target>Използвай сървър</target> @@ -5329,10 +5607,12 @@ To connect, please ask your contact to create another connection link and check </trans-unit> <trans-unit id="Verify code with desktop" xml:space="preserve"> <source>Verify code with desktop</source> + <target>Потвръди кода с настолното устройство</target> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="Verify connection" xml:space="preserve"> <source>Verify connection</source> + <target>Потвръди връзките</target> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="Verify connection security" xml:space="preserve"> @@ -5342,6 +5622,7 @@ To connect, please ask your contact to create another connection link and check </trans-unit> <trans-unit id="Verify connections" xml:space="preserve"> <source>Verify connections</source> + <target>Потвръди връзките</target> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="Verify security code" xml:space="preserve"> @@ -5356,6 +5637,7 @@ To connect, please ask your contact to create another connection link and check </trans-unit> <trans-unit id="Via secure quantum resistant protocol." xml:space="preserve"> <source>Via secure quantum resistant protocol.</source> + <target>Чрез сигурен квантово устойчив протокол.</target> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="Video call" xml:space="preserve"> @@ -5383,6 +5665,11 @@ To connect, please ask your contact to create another connection link and check <target>Виж кода за сигурност</target> <note>No comment provided by engineer.</note> </trans-unit> + <trans-unit id="Visible history" xml:space="preserve"> + <source>Visible history</source> + <target>Видима история</target> + <note>chat feature</note> + </trans-unit> <trans-unit id="Voice messages" xml:space="preserve"> <source>Voice messages</source> <target>Гласови съобщения</target> @@ -5410,6 +5697,7 @@ To connect, please ask your contact to create another connection link and check </trans-unit> <trans-unit id="Waiting for desktop..." xml:space="preserve"> <source>Waiting for desktop...</source> + <target>Изчакване на настолно устройство…</target> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="Waiting for file" xml:space="preserve"> @@ -5467,11 +5755,19 @@ To connect, please ask your contact to create another connection link and check <target>Когато споделяте инкогнито профил с някого, този профил ще се използва за групите, в които той ви кани.</target> <note>No comment provided by engineer.</note> </trans-unit> + <trans-unit id="With encrypted files and media." xml:space="preserve"> + <source>With encrypted files and media.</source> + <note>No comment provided by engineer.</note> + </trans-unit> <trans-unit id="With optional welcome message." xml:space="preserve"> <source>With optional welcome message.</source> <target>С незадължително съобщение при посрещане.</target> <note>No comment provided by engineer.</note> </trans-unit> + <trans-unit id="With reduced battery usage." xml:space="preserve"> + <source>With reduced battery usage.</source> + <note>No comment provided by engineer.</note> + </trans-unit> <trans-unit id="Wrong database passphrase" xml:space="preserve"> <source>Wrong database passphrase</source> <target>Грешна парола за базата данни</target> @@ -5504,7 +5800,7 @@ To connect, please ask your contact to create another connection link and check </trans-unit> <trans-unit id="You already have a chat profile with the same display name. Please choose another name." xml:space="preserve"> <source>You already have a chat profile with the same display name. Please choose another name.</source> - <target>Вече имате чат профил със същото показвано име. Моля, изберете друго име.</target> + <target>Вече имате чат профил със същото име. Моля, изберете друго име.</target> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="You are already connected to %@." xml:space="preserve"> @@ -5514,31 +5810,39 @@ To connect, please ask your contact to create another connection link and check </trans-unit> <trans-unit id="You are already connecting to %@." xml:space="preserve"> <source>You are already connecting to %@.</source> + <target>Вече се свързвате с %@.</target> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="You are already connecting via this one-time link!" xml:space="preserve"> <source>You are already connecting via this one-time link!</source> + <target>Вече се свързвате чрез този еднократен линк за връзка!</target> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="You are already in group %@." xml:space="preserve"> <source>You are already in group %@.</source> + <target>Вече сте в група %@.</target> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="You are already joining the group %@." xml:space="preserve"> <source>You are already joining the group %@.</source> + <target>Вече се присъединявате към групата %@.</target> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="You are already joining the group via this link!" xml:space="preserve"> <source>You are already joining the group via this link!</source> + <target>Вие вече се присъединявате към групата чрез този линк!</target> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="You are already joining the group via this link." xml:space="preserve"> <source>You are already joining the group via this link.</source> + <target>Вие вече се присъединявате към групата чрез този линк.</target> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="You are already joining the group! Repeat join request?" xml:space="preserve"> <source>You are already joining the group! Repeat join request?</source> + <target>Вече се присъединихте към групата! +Изпрати отново заявката за присъединяване?</target> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="You are connected to the server used to receive messages from this contact." xml:space="preserve"> @@ -5556,11 +5860,6 @@ Repeat join request?</source> <target>Можете да приемате обаждания от заключен екран, без идентификация на устройство и приложението.</target> <note>No comment provided by engineer.</note> </trans-unit> - <trans-unit id="You can also connect by clicking the link. If it opens in the browser, click **Open in mobile app** button." xml:space="preserve"> - <source>You can also connect by clicking the link. If it opens in the browser, click **Open in mobile app** button.</source> - <target>Можете също да се свържете, като натиснете върху линка. Ако се отвори в браузъра, натиснете върху бутона **Отваряне в мобилно приложение**.</target> - <note>No comment provided by engineer.</note> - </trans-unit> <trans-unit id="You can create it later" xml:space="preserve"> <source>You can create it later</source> <target>Можете да го създадете по-късно</target> @@ -5581,6 +5880,11 @@ Repeat join request?</source> <target>Можете да скриете или заглушите известията за потребителски профил - плъзнете надясно.</target> <note>No comment provided by engineer.</note> </trans-unit> + <trans-unit id="You can make it visible to your SimpleX contacts via Settings." xml:space="preserve"> + <source>You can make it visible to your SimpleX contacts via Settings.</source> + <target>Можете да го направите видим за вашите контакти в SimpleX чрез Настройки.</target> + <note>No comment provided by engineer.</note> + </trans-unit> <trans-unit id="You can now send messages to %@" xml:space="preserve"> <source>You can now send messages to %@</source> <target>Вече можете да изпращате съобщения до %@</target> @@ -5621,6 +5925,11 @@ Repeat join request?</source> <target>Можете да използвате markdown за форматиране на съобщенията:</target> <note>No comment provided by engineer.</note> </trans-unit> + <trans-unit id="You can view invitation link again in connection details." xml:space="preserve"> + <source>You can view invitation link again in connection details.</source> + <target>Можете да видите отново линкът за покана в подробностите за връзката.</target> + <note>No comment provided by engineer.</note> + </trans-unit> <trans-unit id="You can't send messages!" xml:space="preserve"> <source>You can't send messages!</source> <target>Не може да изпращате съобщения!</target> @@ -5638,11 +5947,14 @@ Repeat join request?</source> </trans-unit> <trans-unit id="You have already requested connection via this address!" xml:space="preserve"> <source>You have already requested connection via this address!</source> + <target>Вече сте заявили връзка през този адрес!</target> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="You have already requested connection! Repeat connection request?" xml:space="preserve"> <source>You have already requested connection! Repeat connection request?</source> + <target>Вече сте направили заявката за връзка! +Изпрати отново заявката за свързване?</target> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="You have no chats" xml:space="preserve"> @@ -5697,6 +6009,7 @@ Repeat connection request?</source> </trans-unit> <trans-unit id="You will be connected when group link host's device is online, please wait or check later!" xml:space="preserve"> <source>You will be connected when group link host's device is online, please wait or check later!</source> + <target>Ще бъдете свързани, когато устройството на хоста на груповата връзка е онлайн, моля, изчакайте или проверете по-късно!</target> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="You will be connected when your connection request is accepted, please wait or check later!" xml:space="preserve"> @@ -5716,6 +6029,7 @@ Repeat connection request?</source> </trans-unit> <trans-unit id="You will connect to all group members." xml:space="preserve"> <source>You will connect to all group members.</source> + <target>Ще се свържете с всички членове на групата.</target> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="You will still receive calls and notifications from muted profiles when they are active." xml:space="preserve"> @@ -5805,13 +6119,6 @@ You can cancel this connection and remove the contact (and try later with a new <target>Вашите контакти могат да позволят пълното изтриване на съобщението.</target> <note>No comment provided by engineer.</note> </trans-unit> - <trans-unit id="Your contacts in SimpleX will see it. You can change it in Settings." xml:space="preserve"> - <source>Your contacts in SimpleX will see it. -You can change it in Settings.</source> - <target>Вашите контакти в SimpleX ще го видят. -Можете да го промените в Настройки.</target> - <note>No comment provided by engineer.</note> - </trans-unit> <trans-unit id="Your contacts will remain connected." xml:space="preserve"> <source>Your contacts will remain connected.</source> <target>Вашите контакти ще останат свързани.</target> @@ -5839,6 +6146,7 @@ You can change it in Settings.</source> </trans-unit> <trans-unit id="Your profile" xml:space="preserve"> <source>Your profile</source> + <target>Вашият профил</target> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="Your profile **%@** will be shared." xml:space="preserve"> @@ -5935,6 +6243,7 @@ SimpleX сървърите не могат да видят вашия профи </trans-unit> <trans-unit id="and %lld other events" xml:space="preserve"> <source>and %lld other events</source> + <target>и %lld други събития</target> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="audio call (not e2e encrypted)" xml:space="preserve"> @@ -5944,6 +6253,7 @@ SimpleX сървърите не могат да видят вашия профи </trans-unit> <trans-unit id="author" xml:space="preserve"> <source>author</source> + <target>автор</target> <note>member role</note> </trans-unit> <trans-unit id="bad message ID" xml:space="preserve"> @@ -5958,8 +6268,17 @@ SimpleX сървърите не могат да видят вашия профи </trans-unit> <trans-unit id="blocked" xml:space="preserve"> <source>blocked</source> + <target>блокиран</target> <note>No comment provided by engineer.</note> </trans-unit> + <trans-unit id="blocked %@" xml:space="preserve"> + <source>blocked %@</source> + <note>rcv group event chat item</note> + </trans-unit> + <trans-unit id="blocked by admin" xml:space="preserve"> + <source>blocked by admin</source> + <note>blocked chat item</note> + </trans-unit> <trans-unit id="bold" xml:space="preserve"> <source>bold</source> <target>удебелен</target> @@ -6080,6 +6399,10 @@ SimpleX сървърите не могат да видят вашия профи <target>връзка:%@</target> <note>connection information</note> </trans-unit> + <trans-unit id="contact %@ changed to %@" xml:space="preserve"> + <source>contact %1$@ changed to %2$@</source> + <note>profile update event chat item</note> + </trans-unit> <trans-unit id="contact has e2e encryption" xml:space="preserve"> <source>contact has e2e encryption</source> <target>контактът има e2e криптиране</target> @@ -6132,6 +6455,7 @@ SimpleX сървърите не могат да видят вашия профи </trans-unit> <trans-unit id="deleted contact" xml:space="preserve"> <source>deleted contact</source> + <target>изтрит контакт</target> <note>rcv direct event chat item</note> </trans-unit> <trans-unit id="deleted group" xml:space="preserve"> @@ -6349,6 +6673,10 @@ SimpleX сървърите не могат да видят вашия профи <target>член</target> <note>member role</note> </trans-unit> + <trans-unit id="member %@ changed to %@" xml:space="preserve"> + <source>member %1$@ changed to %2$@</source> + <note>profile update event chat item</note> + </trans-unit> <trans-unit id="member connected" xml:space="preserve"> <source>connected</source> <target>свързан</target> @@ -6471,6 +6799,14 @@ SimpleX сървърите не могат да видят вашия профи <target>отстранен %@</target> <note>rcv group event chat item</note> </trans-unit> + <trans-unit id="removed contact address" xml:space="preserve"> + <source>removed contact address</source> + <note>profile update event chat item</note> + </trans-unit> + <trans-unit id="removed profile picture" xml:space="preserve"> + <source>removed profile picture</source> + <note>profile update event chat item</note> + </trans-unit> <trans-unit id="removed you" xml:space="preserve"> <source>removed you</source> <target>ви острани</target> @@ -6501,6 +6837,14 @@ SimpleX сървърите не могат да видят вашия профи <target>изпрати лично съобщение</target> <note>No comment provided by engineer.</note> </trans-unit> + <trans-unit id="set new contact address" xml:space="preserve"> + <source>set new contact address</source> + <note>profile update event chat item</note> + </trans-unit> + <trans-unit id="set new profile picture" xml:space="preserve"> + <source>set new profile picture</source> + <note>profile update event chat item</note> + </trans-unit> <trans-unit id="starting…" xml:space="preserve"> <source>starting…</source> <target>стартиране…</target> @@ -6516,18 +6860,31 @@ SimpleX сървърите не могат да видят вашия профи <target>този контакт</target> <note>notification title</note> </trans-unit> + <trans-unit id="unblocked %@" xml:space="preserve"> + <source>unblocked %@</source> + <note>rcv group event chat item</note> + </trans-unit> <trans-unit id="unknown" xml:space="preserve"> <source>unknown</source> <target>неизвестен</target> <note>connection info</note> </trans-unit> + <trans-unit id="unknown status" xml:space="preserve"> + <source>unknown status</source> + <note>No comment provided by engineer.</note> + </trans-unit> <trans-unit id="updated group profile" xml:space="preserve"> <source>updated group profile</source> <target>актуализиран профил на групата</target> <note>rcv group event chat item</note> </trans-unit> + <trans-unit id="updated profile" xml:space="preserve"> + <source>updated profile</source> + <note>profile update event chat item</note> + </trans-unit> <trans-unit id="v%@" xml:space="preserve"> <source>v%@</source> + <target>v%@</target> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="v%@ (%@)" xml:space="preserve"> @@ -6595,6 +6952,10 @@ SimpleX сървърите не могат да видят вашия профи <target>вие сте наблюдател</target> <note>No comment provided by engineer.</note> </trans-unit> + <trans-unit id="you blocked %@" xml:space="preserve"> + <source>you blocked %@</source> + <note>snd group event chat item</note> + </trans-unit> <trans-unit id="you changed address" xml:space="preserve"> <source>you changed address</source> <target>променихте адреса</target> @@ -6635,6 +6996,10 @@ SimpleX сървърите не могат да видят вашия профи <target>споделихте еднократен инкогнито линк за връзка</target> <note>chat list item description</note> </trans-unit> + <trans-unit id="you unblocked %@" xml:space="preserve"> + <source>you unblocked %@</source> + <note>snd group event chat item</note> + </trans-unit> <trans-unit id="you: " xml:space="preserve"> <source>you: </source> <target>вие: </target> @@ -6669,6 +7034,7 @@ SimpleX сървърите не могат да видят вашия профи </trans-unit> <trans-unit id="NSLocalNetworkUsageDescription" xml:space="preserve"> <source>SimpleX uses local network access to allow using user chat profile via desktop app on the same network.</source> + <target>SimpleX използва достъп до локална мрежа, за да позволи използването на потребителския чат профил чрез настолно приложение в същата мрежа.</target> <note>Privacy - Local Network Usage Description</note> </trans-unit> <trans-unit id="NSMicrophoneUsageDescription" xml:space="preserve"> diff --git a/apps/ios/SimpleX Localizations/cs.xcloc/Localized Contents/cs.xliff b/apps/ios/SimpleX Localizations/cs.xcloc/Localized Contents/cs.xliff index be8b23658b..a376c86ad1 100644 --- a/apps/ios/SimpleX Localizations/cs.xcloc/Localized Contents/cs.xliff +++ b/apps/ios/SimpleX Localizations/cs.xcloc/Localized Contents/cs.xliff @@ -89,6 +89,7 @@ </trans-unit> <trans-unit id="%@ and %@" xml:space="preserve"> <source>%@ and %@</source> + <target>%@ a %@</target> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="%@ and %@ connected" xml:space="preserve"> @@ -103,6 +104,7 @@ </trans-unit> <trans-unit id="%@ connected" xml:space="preserve"> <source>%@ connected</source> + <target>%@ připojen</target> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="%@ is connected!" xml:space="preserve"> @@ -212,6 +214,10 @@ <source>%lld messages blocked</source> <note>No comment provided by engineer.</note> </trans-unit> + <trans-unit id="%lld messages blocked by admin" xml:space="preserve"> + <source>%lld messages blocked by admin</source> + <note>No comment provided by engineer.</note> + </trans-unit> <trans-unit id="%lld messages marked deleted" xml:space="preserve"> <source>%lld messages marked deleted</source> <note>No comment provided by engineer.</note> @@ -303,14 +309,17 @@ <target>)</target> <note>No comment provided by engineer.</note> </trans-unit> + <trans-unit id="**Add contact**: to create a new invitation link, or connect via a link you received." xml:space="preserve"> + <source>**Add contact**: to create a new invitation link, or connect via a link you received.</source> + <note>No comment provided by engineer.</note> + </trans-unit> <trans-unit id="**Add new contact**: to create your one-time QR Code for your contact." xml:space="preserve"> <source>**Add new contact**: to create your one-time QR Code or link for your contact.</source> <target>**Přidat nový kontakt**: pro vytvoření jednorázového QR kódu nebo odkazu pro váš kontakt.</target> <note>No comment provided by engineer.</note> </trans-unit> - <trans-unit id="**Create link / QR code** for your contact to use." xml:space="preserve"> - <source>**Create link / QR code** for your contact to use.</source> - <target>**Vytvořte odkaz / QR kód** pro váš kontakt.</target> + <trans-unit id="**Create group**: to create a new group." xml:space="preserve"> + <source>**Create group**: to create a new group.</source> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="**More private**: check new messages every 20 minutes. Device token is shared with SimpleX Chat server, but not how many contacts or messages you have." xml:space="preserve"> @@ -323,11 +332,6 @@ <target>**Nejsoukromější**: nepoužívejte server oznámení SimpleX Chat, pravidelně kontrolujte zprávy na pozadí (závisí na tom, jak často aplikaci používáte).</target> <note>No comment provided by engineer.</note> </trans-unit> - <trans-unit id="**Paste received link** or open it in the browser and tap **Open in mobile app**." xml:space="preserve"> - <source>**Paste received link** or open it in the browser and tap **Open in mobile app**.</source> - <target>**Vložte přijatý odkaz** nebo jej otevřete v prohlížeči a klepněte na **Otevřít v mobilní aplikaci**.</target> - <note>No comment provided by engineer.</note> - </trans-unit> <trans-unit id="**Please note**: you will NOT be able to recover or change passphrase if you lose it." xml:space="preserve"> <source>**Please note**: you will NOT be able to recover or change passphrase if you lose it.</source> <target>**Upozornění**: Pokud heslo ztratíte, NEBUDETE jej moci obnovit ani změnit.</target> @@ -338,11 +342,6 @@ <target>**Doporučeno**: Token zařízení a oznámení se odesílají na oznamovací server SimpleX Chat, ale nikoli obsah, velikost nebo od koho jsou zprávy.</target> <note>No comment provided by engineer.</note> </trans-unit> - <trans-unit id="**Scan QR code**: to connect to your contact in person or via video call." xml:space="preserve"> - <source>**Scan QR code**: to connect to your contact in person or via video call.</source> - <target>** Naskenujte QR kód**: pro připojení ke kontaktu osobně nebo prostřednictvím videohovoru.</target> - <note>No comment provided by engineer.</note> - </trans-unit> <trans-unit id="**Warning**: Instant push notifications require passphrase saved in Keychain." xml:space="preserve"> <source>**Warning**: Instant push notifications require passphrase saved in Keychain.</source> <target>**Upozornění**: Okamžitě doručovaná oznámení vyžadují přístupové heslo uložené v Klíčence.</target> @@ -372,7 +371,7 @@ <source>- connect to [directory service](simplex:/contact#/?v=1-4&smp=smp%3A%2F%2Fu2dS9sG8nMNURyZwqASV4yROM28Er0luVTx5X1CsMrU%3D%40smp4.simplex.im%2FeXSPwqTkKyDO3px4fLf1wx3MvPdjdLW3%23%2F%3Fv%3D1-2%26dh%3DMCowBQYDK2VuAyEAaiv6MkMH44L2TcYrt_CsX3ZvM11WgbMEUn0hkIKTOho%253D%26srv%3Do5vmywmrnaxalvz6wi3zicyftgio6psuvyniis6gco6bp6ekl4cqj4id.onion) (BETA)! - delivery receipts (up to 20 members). - faster and more stable.</source> - <target>- připojit k [adresářová služba](simplex:/contact#/?v=1-4&smp=smp%3A%2F%2Fu2dS9sG8nMNURyZwqASV4yROM28Er0luVTx5X1CsMrU%3D%40smp4.simplex.im%2FeXSPwqTkKyDO3px4fLf1wx3MvPdjdLW3%23%2F%3Fv%3D1-2%26dh%3DMCowBQYDK2VuAyEAaiv6MkMH44L2TcYrt_CsX3ZvM11WgbMEUn0hkIKTOho%253D%26srv%3Do5vmywmrnaxalvz6wi3zicyftgio6psuvyniis6gco6bp6ekl4cqj4id.cibule) (BETA)! + <target>- připojit k [adresářová služba](simplex:/contact#/?v=1-4&smp=smp%3A%2F%2Fu2dS9sG8nMNURyZwqASV4yROM28Er0luVTx5X1CsMrU%3D%40smp4.simplex.im%2FeXSPwqTkKyDO3px4fLf1wx3MvPdjdLW3%23%2F%3Fv%3D1-2%26dh%3DMCowBQYDK2VuAyEAaiv6MkMH44L2TcYrt_CsX3ZvM11WgbMEUn0hkIKTOho%253D%26srv%3Do5vmywmrnaxalvz6wi3zicyftgio6psuvyniis6gco6bp6ekl4cqj4id.onion) (BETA)! - doručenky (až 20 členů). - Rychlejší a stabilnější.</target> <note>No comment provided by engineer.</note> @@ -440,11 +439,6 @@ <target>1 týden</target> <note>time interval</note> </trans-unit> - <trans-unit id="1-time link" xml:space="preserve"> - <source>1-time link</source> - <target>Jednorázový odkaz</target> - <note>No comment provided by engineer.</note> - </trans-unit> <trans-unit id="5 minutes" xml:space="preserve"> <source>5 minutes</source> <target>5 minut</target> @@ -560,6 +554,10 @@ <target>Přidejte adresu do svého profilu, aby ji vaše kontakty mohly sdílet s dalšími lidmi. Aktualizace profilu bude zaslána vašim kontaktům.</target> <note>No comment provided by engineer.</note> </trans-unit> + <trans-unit id="Add contact" xml:space="preserve"> + <source>Add contact</source> + <note>No comment provided by engineer.</note> + </trans-unit> <trans-unit id="Add preset servers" xml:space="preserve"> <source>Add preset servers</source> <target>Přidejte přednastavené servery</target> @@ -630,6 +628,10 @@ <target>Všichni členové skupiny zůstanou připojeni.</target> <note>No comment provided by engineer.</note> </trans-unit> + <trans-unit id="All messages will be deleted - this cannot be undone!" xml:space="preserve"> + <source>All messages will be deleted - this cannot be undone!</source> + <note>No comment provided by engineer.</note> + </trans-unit> <trans-unit id="All messages will be deleted - this cannot be undone! The messages will be deleted ONLY for you." xml:space="preserve"> <source>All messages will be deleted - this cannot be undone! The messages will be deleted ONLY for you.</source> <target>Všechny zprávy budou smazány – tuto akci nelze vrátit zpět! Zprávy budou smazány POUZE pro vás.</target> @@ -664,9 +666,9 @@ <target>Povolte mizící zprávy, pouze pokud vám to váš kontakt dovolí.</target> <note>No comment provided by engineer.</note> </trans-unit> - <trans-unit id="Allow irreversible message deletion only if your contact allows it to you." xml:space="preserve"> - <source>Allow irreversible message deletion only if your contact allows it to you.</source> - <target>Povolte nevratné smazání zprávy pouze v případě, že vám to váš kontakt dovolí.</target> + <trans-unit id="Allow irreversible message deletion only if your contact allows it to you. (24 hours)" xml:space="preserve"> + <source>Allow irreversible message deletion only if your contact allows it to you. (24 hours)</source> + <target>Povolte nevratné smazání zprávy pouze v případě, že vám to váš kontakt dovolí. (24 hodin)</target> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="Allow message reactions only if your contact allows them." xml:space="preserve"> @@ -689,9 +691,9 @@ <target>Povolit odesílání mizících zpráv.</target> <note>No comment provided by engineer.</note> </trans-unit> - <trans-unit id="Allow to irreversibly delete sent messages." xml:space="preserve"> - <source>Allow to irreversibly delete sent messages.</source> - <target>Povolit nevratné smazání odeslaných zpráv.</target> + <trans-unit id="Allow to irreversibly delete sent messages. (24 hours)" xml:space="preserve"> + <source>Allow to irreversibly delete sent messages. (24 hours)</source> + <target>Povolit nevratné smazání odeslaných zpráv. (24 hodin)</target> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="Allow to send files and media." xml:space="preserve"> @@ -724,9 +726,9 @@ <target>Povolte svým kontaktům vám volat.</target> <note>No comment provided by engineer.</note> </trans-unit> - <trans-unit id="Allow your contacts to irreversibly delete sent messages." xml:space="preserve"> - <source>Allow your contacts to irreversibly delete sent messages.</source> - <target>Umožněte svým kontaktům nevratně odstranit odeslané zprávy.</target> + <trans-unit id="Allow your contacts to irreversibly delete sent messages. (24 hours)" xml:space="preserve"> + <source>Allow your contacts to irreversibly delete sent messages. (24 hours)</source> + <target>Umožněte svým kontaktům nevratně odstranit odeslané zprávy. (24 hodin)</target> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="Allow your contacts to send disappearing messages." xml:space="preserve"> @@ -899,6 +901,10 @@ <source>Block</source> <note>No comment provided by engineer.</note> </trans-unit> + <trans-unit id="Block for all" xml:space="preserve"> + <source>Block for all</source> + <note>No comment provided by engineer.</note> + </trans-unit> <trans-unit id="Block group members" xml:space="preserve"> <source>Block group members</source> <note>No comment provided by engineer.</note> @@ -907,18 +913,26 @@ <source>Block member</source> <note>No comment provided by engineer.</note> </trans-unit> + <trans-unit id="Block member for all?" xml:space="preserve"> + <source>Block member for all?</source> + <note>No comment provided by engineer.</note> + </trans-unit> <trans-unit id="Block member?" xml:space="preserve"> <source>Block member?</source> <note>No comment provided by engineer.</note> </trans-unit> + <trans-unit id="Blocked by admin" xml:space="preserve"> + <source>Blocked by admin</source> + <note>No comment provided by engineer.</note> + </trans-unit> <trans-unit id="Both you and your contact can add message reactions." xml:space="preserve"> <source>Both you and your contact can add message reactions.</source> <target>Vy i váš kontakt můžete přidávat reakce na zprávy.</target> <note>No comment provided by engineer.</note> </trans-unit> - <trans-unit id="Both you and your contact can irreversibly delete sent messages." xml:space="preserve"> - <source>Both you and your contact can irreversibly delete sent messages.</source> - <target>Vy i váš kontakt můžete nevratně mazat odeslané zprávy.</target> + <trans-unit id="Both you and your contact can irreversibly delete sent messages. (24 hours)" xml:space="preserve"> + <source>Both you and your contact can irreversibly delete sent messages. (24 hours)</source> + <target>Vy i váš kontakt můžete nevratně mazat odeslané zprávy. (24 hodin)</target> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="Both you and your contact can make calls." xml:space="preserve"> @@ -956,9 +970,8 @@ <target>Hovory</target> <note>No comment provided by engineer.</note> </trans-unit> - <trans-unit id="Can't delete user profile!" xml:space="preserve"> - <source>Can't delete user profile!</source> - <target>Nemohu smazat uživatelský profil!</target> + <trans-unit id="Camera not available" xml:space="preserve"> + <source>Camera not available</source> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="Can't invite contact!" xml:space="preserve"> @@ -1072,6 +1085,10 @@ <target>Chat je zastaven</target> <note>No comment provided by engineer.</note> </trans-unit> + <trans-unit id="Chat is stopped. If you already used this database on another device, you should transfer it back before starting chat." xml:space="preserve"> + <source>Chat is stopped. If you already used this database on another device, you should transfer it back before starting chat.</source> + <note>No comment provided by engineer.</note> + </trans-unit> <trans-unit id="Chat preferences" xml:space="preserve"> <source>Chat preferences</source> <target>Předvolby chatu</target> @@ -1117,6 +1134,10 @@ <target>Vyčistit konverzaci?</target> <note>No comment provided by engineer.</note> </trans-unit> + <trans-unit id="Clear private notes?" xml:space="preserve"> + <source>Clear private notes?</source> + <note>No comment provided by engineer.</note> + </trans-unit> <trans-unit id="Clear verification" xml:space="preserve"> <source>Clear verification</source> <target>Zrušte ověření</target> @@ -1208,11 +1229,6 @@ This is your own one-time link!</source> <target>Připojte se prostřednictvím odkazu</target> <note>No comment provided by engineer.</note> </trans-unit> - <trans-unit id="Connect via link / QR code" xml:space="preserve"> - <source>Connect via link / QR code</source> - <target>Připojit se prostřednictvím odkazu / QR kódu</target> - <note>No comment provided by engineer.</note> - </trans-unit> <trans-unit id="Connect via one-time link" xml:space="preserve"> <source>Connect via one-time link</source> <target>Připojit se jednorázovým odkazem</target> @@ -1380,11 +1396,6 @@ This is your own one-time link!</source> <target>Vytvořit nový profil v [desktop app](https://simplex.chat/downloads/). 💻</target> <note>No comment provided by engineer.</note> </trans-unit> - <trans-unit id="Create one-time invitation link" xml:space="preserve"> - <source>Create one-time invitation link</source> - <target>Vytvořit jednorázovou pozvánku</target> - <note>No comment provided by engineer.</note> - </trans-unit> <trans-unit id="Create profile" xml:space="preserve"> <source>Create profile</source> <note>No comment provided by engineer.</note> @@ -1404,11 +1415,23 @@ This is your own one-time link!</source> <target>Vytvořte si profil</target> <note>No comment provided by engineer.</note> </trans-unit> + <trans-unit id="Created at" xml:space="preserve"> + <source>Created at</source> + <note>No comment provided by engineer.</note> + </trans-unit> + <trans-unit id="Created at: %@" xml:space="preserve"> + <source>Created at: %@</source> + <note>copied message info</note> + </trans-unit> <trans-unit id="Created on %@" xml:space="preserve"> <source>Created on %@</source> <target>Vytvořeno na %@</target> <note>No comment provided by engineer.</note> </trans-unit> + <trans-unit id="Creating link…" xml:space="preserve"> + <source>Creating link…</source> + <note>No comment provided by engineer.</note> + </trans-unit> <trans-unit id="Current Passcode" xml:space="preserve"> <source>Current Passcode</source> <target>Aktuální heslo</target> @@ -1880,6 +1903,10 @@ This cannot be undone!</source> <target>Udělat později</target> <note>No comment provided by engineer.</note> </trans-unit> + <trans-unit id="Do not send history to new members." xml:space="preserve"> + <source>Do not send history to new members.</source> + <note>No comment provided by engineer.</note> + </trans-unit> <trans-unit id="Don't create address" xml:space="preserve"> <source>Don't create address</source> <target>Nevytvářet adresu</target> @@ -1950,6 +1977,10 @@ This cannot be undone!</source> <target>Povolit automatické mazání zpráv?</target> <note>No comment provided by engineer.</note> </trans-unit> + <trans-unit id="Enable camera access" xml:space="preserve"> + <source>Enable camera access</source> + <note>No comment provided by engineer.</note> + </trans-unit> <trans-unit id="Enable for all" xml:space="preserve"> <source>Enable for all</source> <target>Povolit pro všechny</target> @@ -2015,6 +2046,10 @@ This cannot be undone!</source> <target>Šifrovaná zpráva nebo jiná událost</target> <note>notification</note> </trans-unit> + <trans-unit id="Encrypted message: app is stopped" xml:space="preserve"> + <source>Encrypted message: app is stopped</source> + <note>notification</note> + </trans-unit> <trans-unit id="Encrypted message: database error" xml:space="preserve"> <source>Encrypted message: database error</source> <target>Šifrovaná zpráva: chyba databáze</target> @@ -2155,6 +2190,10 @@ This cannot be undone!</source> <target>Chyba vytvoření kontaktu člena</target> <note>No comment provided by engineer.</note> </trans-unit> + <trans-unit id="Error creating message" xml:space="preserve"> + <source>Error creating message</source> + <note>No comment provided by engineer.</note> + </trans-unit> <trans-unit id="Error creating profile!" xml:space="preserve"> <source>Error creating profile!</source> <target>Chyba při vytváření profilu!</target> @@ -2240,6 +2279,10 @@ This cannot be undone!</source> <target>Chyba načítání %@ serverů</target> <note>No comment provided by engineer.</note> </trans-unit> + <trans-unit id="Error opening chat" xml:space="preserve"> + <source>Error opening chat</source> + <note>No comment provided by engineer.</note> + </trans-unit> <trans-unit id="Error receiving file" xml:space="preserve"> <source>Error receiving file</source> <target>Chyba při příjmu souboru</target> @@ -2280,6 +2323,10 @@ This cannot be undone!</source> <target>Chyba ukládání hesla uživatele</target> <note>No comment provided by engineer.</note> </trans-unit> + <trans-unit id="Error scanning code: %@" xml:space="preserve"> + <source>Error scanning code: %@</source> + <note>No comment provided by engineer.</note> + </trans-unit> <trans-unit id="Error sending email" xml:space="preserve"> <source>Error sending email</source> <target>Chyba odesílání e-mailu</target> @@ -2604,9 +2651,9 @@ This cannot be undone!</source> <target>Členové skupin mohou přidávat reakce na zprávy.</target> <note>No comment provided by engineer.</note> </trans-unit> - <trans-unit id="Group members can irreversibly delete sent messages." xml:space="preserve"> - <source>Group members can irreversibly delete sent messages.</source> - <target>Členové skupiny mohou nevratně mazat odeslané zprávy.</target> + <trans-unit id="Group members can irreversibly delete sent messages. (24 hours)" xml:space="preserve"> + <source>Group members can irreversibly delete sent messages. (24 hours)</source> + <target>Členové skupiny mohou nevratně mazat odeslané zprávy. (24 hodin)</target> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="Group members can send direct messages." xml:space="preserve"> @@ -2714,6 +2761,10 @@ This cannot be undone!</source> <target>Historie</target> <note>No comment provided by engineer.</note> </trans-unit> + <trans-unit id="History is not sent to new members." xml:space="preserve"> + <source>History is not sent to new members.</source> + <note>No comment provided by engineer.</note> + </trans-unit> <trans-unit id="How SimpleX works" xml:space="preserve"> <source>How SimpleX works</source> <target>Jak SimpleX funguje</target> @@ -2749,11 +2800,6 @@ This cannot be undone!</source> <target>Pokud se nemůžete setkat osobně, zobrazte QR kód ve videohovoru nebo sdílejte odkaz.</target> <note>No comment provided by engineer.</note> </trans-unit> - <trans-unit id="If you cannot meet in person, you can **scan QR code in the video call**, or your contact can share an invitation link." xml:space="preserve"> - <source>If you cannot meet in person, you can **scan QR code in the video call**, or your contact can share an invitation link.</source> - <target>Pokud se nemůžete setkat osobně, můžete **naskenovat QR kód během videohovoru**, nebo váš kontakt může sdílet odkaz na pozvánku.</target> - <note>No comment provided by engineer.</note> - </trans-unit> <trans-unit id="If you enter this passcode when opening the app, all app data will be irreversibly removed!" xml:space="preserve"> <source>If you enter this passcode when opening the app, all app data will be irreversibly removed!</source> <target>Pokud tento přístupový kód zadáte při otevření aplikace, všechna data budou nenávratně smazána!</target> @@ -2809,6 +2855,10 @@ This cannot be undone!</source> <target>Import databáze</target> <note>No comment provided by engineer.</note> </trans-unit> + <trans-unit id="Improved message delivery" xml:space="preserve"> + <source>Improved message delivery</source> + <note>No comment provided by engineer.</note> + </trans-unit> <trans-unit id="Improved privacy and security" xml:space="preserve"> <source>Improved privacy and security</source> <target>Vylepšená ochrana soukromí a zabezpečení</target> @@ -2909,15 +2959,31 @@ This cannot be undone!</source> <target>Rozhranní</target> <note>No comment provided by engineer.</note> </trans-unit> + <trans-unit id="Invalid QR code" xml:space="preserve"> + <source>Invalid QR code</source> + <note>No comment provided by engineer.</note> + </trans-unit> <trans-unit id="Invalid connection link" xml:space="preserve"> <source>Invalid connection link</source> <target>Neplatný odkaz na spojení</target> <note>No comment provided by engineer.</note> </trans-unit> + <trans-unit id="Invalid display name!" xml:space="preserve"> + <source>Invalid display name!</source> + <note>No comment provided by engineer.</note> + </trans-unit> + <trans-unit id="Invalid link" xml:space="preserve"> + <source>Invalid link</source> + <note>No comment provided by engineer.</note> + </trans-unit> <trans-unit id="Invalid name!" xml:space="preserve"> <source>Invalid name!</source> <note>No comment provided by engineer.</note> </trans-unit> + <trans-unit id="Invalid response" xml:space="preserve"> + <source>Invalid response</source> + <note>No comment provided by engineer.</note> + </trans-unit> <trans-unit id="Invalid server address!" xml:space="preserve"> <source>Invalid server address!</source> <target>Neplatná adresa serveru!</target> @@ -3009,6 +3075,10 @@ This cannot be undone!</source> <target>Připojit ke skupině</target> <note>No comment provided by engineer.</note> </trans-unit> + <trans-unit id="Join group conversations" xml:space="preserve"> + <source>Join group conversations</source> + <note>No comment provided by engineer.</note> + </trans-unit> <trans-unit id="Join group?" xml:space="preserve"> <source>Join group?</source> <note>No comment provided by engineer.</note> @@ -3032,10 +3102,18 @@ This is your link for group %@!</source> <target>Připojování ke skupině</target> <note>No comment provided by engineer.</note> </trans-unit> + <trans-unit id="Keep" xml:space="preserve"> + <source>Keep</source> + <note>No comment provided by engineer.</note> + </trans-unit> <trans-unit id="Keep the app open to use it from desktop" xml:space="preserve"> <source>Keep the app open to use it from desktop</source> <note>No comment provided by engineer.</note> </trans-unit> + <trans-unit id="Keep unused invitation?" xml:space="preserve"> + <source>Keep unused invitation?</source> + <note>No comment provided by engineer.</note> + </trans-unit> <trans-unit id="Keep your connections" xml:space="preserve"> <source>Keep your connections</source> <target>Zachovat vaše připojení</target> @@ -3118,6 +3196,11 @@ This is your link for group %@!</source> <target>Živé zprávy</target> <note>No comment provided by engineer.</note> </trans-unit> + <trans-unit id="Local" xml:space="preserve"> + <source>Local</source> + <target>Místní</target> + <note>No comment provided by engineer.</note> + </trans-unit> <trans-unit id="Local name" xml:space="preserve"> <source>Local name</source> <target>Místní název</target> @@ -3357,6 +3440,10 @@ This is your link for group %@!</source> <target>Nové heslo</target> <note>No comment provided by engineer.</note> </trans-unit> + <trans-unit id="New chat" xml:space="preserve"> + <source>New chat</source> + <note>No comment provided by engineer.</note> + </trans-unit> <trans-unit id="New contact request" xml:space="preserve"> <source>New contact request</source> <target>Žádost o nový kontakt</target> @@ -3480,16 +3567,15 @@ This is your link for group %@!</source> - zakázat členy (role "pozorovatel")</target> <note>No comment provided by engineer.</note> </trans-unit> + <trans-unit id="OK" xml:space="preserve"> + <source>OK</source> + <note>No comment provided by engineer.</note> + </trans-unit> <trans-unit id="Off" xml:space="preserve"> <source>Off</source> <target>Vypnout</target> <note>No comment provided by engineer.</note> </trans-unit> - <trans-unit id="Off (Local)" xml:space="preserve"> - <source>Off (Local)</source> - <target>Vypnuto (místní)</target> - <note>No comment provided by engineer.</note> - </trans-unit> <trans-unit id="Ok" xml:space="preserve"> <source>Ok</source> <target>Ok</target> @@ -3550,9 +3636,9 @@ This is your link for group %@!</source> <target>Reakce na zprávy můžete přidávat pouze vy.</target> <note>No comment provided by engineer.</note> </trans-unit> - <trans-unit id="Only you can irreversibly delete messages (your contact can mark them for deletion)." xml:space="preserve"> - <source>Only you can irreversibly delete messages (your contact can mark them for deletion).</source> - <target>Nevratně mazat zprávy můžete pouze vy (váš kontakt je může označit ke smazání).</target> + <trans-unit id="Only you can irreversibly delete messages (your contact can mark them for deletion). (24 hours)" xml:space="preserve"> + <source>Only you can irreversibly delete messages (your contact can mark them for deletion). (24 hours)</source> + <target>Nevratně mazat zprávy můžete pouze vy (váš kontakt je může označit ke smazání). (24 hodin)</target> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="Only you can make calls." xml:space="preserve"> @@ -3575,9 +3661,9 @@ This is your link for group %@!</source> <target>Reakce na zprávy může přidávat pouze váš kontakt.</target> <note>No comment provided by engineer.</note> </trans-unit> - <trans-unit id="Only your contact can irreversibly delete messages (you can mark them for deletion)." xml:space="preserve"> - <source>Only your contact can irreversibly delete messages (you can mark them for deletion).</source> - <target>Nevratně mazat zprávy může pouze váš kontakt (vy je můžete označit ke smazání).</target> + <trans-unit id="Only your contact can irreversibly delete messages (you can mark them for deletion). (24 hours)" xml:space="preserve"> + <source>Only your contact can irreversibly delete messages (you can mark them for deletion). (24 hours)</source> + <target>Nevratně mazat zprávy může pouze váš kontakt (vy je můžete označit ke smazání). (24 hodin)</target> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="Only your contact can make calls." xml:space="preserve"> @@ -3629,9 +3715,16 @@ This is your link for group %@!</source> <target>Protokol a kód s otevřeným zdrojovým kódem - servery může provozovat kdokoli.</target> <note>No comment provided by engineer.</note> </trans-unit> - <trans-unit id="Opening database…" xml:space="preserve"> - <source>Opening database…</source> - <target>Otvírání databáze…</target> + <trans-unit id="Opening app…" xml:space="preserve"> + <source>Opening app…</source> + <note>No comment provided by engineer.</note> + </trans-unit> + <trans-unit id="Or scan QR code" xml:space="preserve"> + <source>Or scan QR code</source> + <note>No comment provided by engineer.</note> + </trans-unit> + <trans-unit id="Or show this code" xml:space="preserve"> + <source>Or show this code</source> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="PING count" xml:space="preserve"> @@ -3674,10 +3767,9 @@ This is your link for group %@!</source> <target>Heslo k zobrazení</target> <note>No comment provided by engineer.</note> </trans-unit> - <trans-unit id="Paste" xml:space="preserve"> - <source>Paste</source> - <target>Vložit</target> - <note>No comment provided by engineer.</note> + <trans-unit id="Past member %@" xml:space="preserve"> + <source>Past member %@</source> + <note>past/unknown group member</note> </trans-unit> <trans-unit id="Paste desktop address" xml:space="preserve"> <source>Paste desktop address</source> @@ -3688,15 +3780,13 @@ This is your link for group %@!</source> <target>Vložit obrázek</target> <note>No comment provided by engineer.</note> </trans-unit> - <trans-unit id="Paste received link" xml:space="preserve"> - <source>Paste received link</source> - <target>Vložení přijatého odkazu</target> + <trans-unit id="Paste link to connect!" xml:space="preserve"> + <source>Paste link to connect!</source> <note>No comment provided by engineer.</note> </trans-unit> - <trans-unit id="Paste the link you received to connect with your contact." xml:space="preserve"> - <source>Paste the link you received to connect with your contact.</source> - <target>Vložte odkaz, který jste obdrželi, do pole níže a spojte se se svým kontaktem.</target> - <note>placeholder</note> + <trans-unit id="Paste the link you received" xml:space="preserve"> + <source>Paste the link you received</source> + <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="People can connect to you only via the links you share." xml:space="preserve"> <source>People can connect to you only via the links you share.</source> @@ -3733,6 +3823,11 @@ This is your link for group %@!</source> <target>Zkontrolujte prosím nastavení své i svého kontaktu.</target> <note>No comment provided by engineer.</note> </trans-unit> + <trans-unit id="Please contact developers. Error: %@" xml:space="preserve"> + <source>Please contact developers. +Error: %@</source> + <note>No comment provided by engineer.</note> + </trans-unit> <trans-unit id="Please contact group admin." xml:space="preserve"> <source>Please contact group admin.</source> <target>Kontaktujte prosím správce skupiny.</target> @@ -3818,6 +3913,10 @@ This is your link for group %@!</source> <target>Soukromé názvy souborů</target> <note>No comment provided by engineer.</note> </trans-unit> + <trans-unit id="Private notes" xml:space="preserve"> + <source>Private notes</source> + <note>name of notes to self</note> + </trans-unit> <trans-unit id="Profile and server connections" xml:space="preserve"> <source>Profile and server connections</source> <target>Profil a připojení k serveru</target> @@ -3936,6 +4035,10 @@ This is your link for group %@!</source> <target>Další informace naleznete v [Uživatelské příručce](https://simplex.chat/docs/guide/app-settings.html#your-simplex-contact-address).</target> <note>No comment provided by engineer.</note> </trans-unit> + <trans-unit id="Read more in [User Guide](https://simplex.chat/docs/guide/chat-profiles.html#incognito-mode)." xml:space="preserve"> + <source>Read more in [User Guide](https://simplex.chat/docs/guide/chat-profiles.html#incognito-mode).</source> + <note>No comment provided by engineer.</note> + </trans-unit> <trans-unit id="Read more in [User Guide](https://simplex.chat/docs/guide/readme.html#connect-to-friends)." xml:space="preserve"> <source>Read more in [User Guide](https://simplex.chat/docs/guide/readme.html#connect-to-friends).</source> <target>Přečtěte si více v [Uživatelské příručce](https://simplex.chat/docs/guide/readme.html#connect-to-friends).</target> @@ -3991,6 +4094,10 @@ This is your link for group %@!</source> <target>Příjem přes</target> <note>No comment provided by engineer.</note> </trans-unit> + <trans-unit id="Recent history and improved [directory bot](simplex:/contact#/?v=1-4&smp=smp%3A%2F%2Fu2dS9sG8nMNURyZwqASV4yROM28Er0luVTx5X1CsMrU%3D%40smp4.simplex.im%2FeXSPwqTkKyDO3px4fLf1wx3MvPdjdLW3%23%2F%3Fv%3D1-2%26dh%3DMCowBQYDK2VuAyEAaiv6MkMH44L2TcYrt_CsX3ZvM11WgbMEUn0hkIKTOho%253D%26srv%3Do5vmywmrnaxalvz6wi3zicyftgio6psuvyniis6gco6bp6ekl4cqj4id.onion)." xml:space="preserve"> + <source>Recent history and improved [directory bot](simplex:/contact#/?v=1-4&smp=smp%3A%2F%2Fu2dS9sG8nMNURyZwqASV4yROM28Er0luVTx5X1CsMrU%3D%40smp4.simplex.im%2FeXSPwqTkKyDO3px4fLf1wx3MvPdjdLW3%23%2F%3Fv%3D1-2%26dh%3DMCowBQYDK2VuAyEAaiv6MkMH44L2TcYrt_CsX3ZvM11WgbMEUn0hkIKTOho%253D%26srv%3Do5vmywmrnaxalvz6wi3zicyftgio6psuvyniis6gco6bp6ekl4cqj4id.onion).</source> + <note>No comment provided by engineer.</note> + </trans-unit> <trans-unit id="Recipients see updates as you type them." xml:space="preserve"> <source>Recipients see updates as you type them.</source> <target>Příjemci uvidí aktualizace během jejich psaní.</target> @@ -4144,6 +4251,10 @@ This is your link for group %@!</source> <target>Chyba obnovení databáze</target> <note>No comment provided by engineer.</note> </trans-unit> + <trans-unit id="Retry" xml:space="preserve"> + <source>Retry</source> + <note>No comment provided by engineer.</note> + </trans-unit> <trans-unit id="Reveal" xml:space="preserve"> <source>Reveal</source> <target>Odhalit</target> @@ -4269,6 +4380,10 @@ This is your link for group %@!</source> <target>Uložené servery WebRTC ICE budou odstraněny</target> <note>No comment provided by engineer.</note> </trans-unit> + <trans-unit id="Saved message" xml:space="preserve"> + <source>Saved message</source> + <note>message info title</note> + </trans-unit> <trans-unit id="Scan QR code" xml:space="preserve"> <source>Scan QR code</source> <target>Skenovat QR kód</target> @@ -4298,6 +4413,14 @@ This is your link for group %@!</source> <target>Hledat</target> <note>No comment provided by engineer.</note> </trans-unit> + <trans-unit id="Search bar accepts invitation links." xml:space="preserve"> + <source>Search bar accepts invitation links.</source> + <note>No comment provided by engineer.</note> + </trans-unit> + <trans-unit id="Search or paste SimpleX link" xml:space="preserve"> + <source>Search or paste SimpleX link</source> + <note>No comment provided by engineer.</note> + </trans-unit> <trans-unit id="Secure queue" xml:space="preserve"> <source>Secure queue</source> <target>Zabezpečit frontu</target> @@ -4403,6 +4526,10 @@ This is your link for group %@!</source> <target>Odeslat je z galerie nebo vlastní klávesnice.</target> <note>No comment provided by engineer.</note> </trans-unit> + <trans-unit id="Send up to 100 last messages to new members." xml:space="preserve"> + <source>Send up to 100 last messages to new members.</source> + <note>No comment provided by engineer.</note> + </trans-unit> <trans-unit id="Sender cancelled file transfer." xml:space="preserve"> <source>Sender cancelled file transfer.</source> <target>Odesílatel zrušil přenos souboru.</target> @@ -4572,9 +4699,8 @@ This is your link for group %@!</source> <target>Sdílet odkaz</target> <note>No comment provided by engineer.</note> </trans-unit> - <trans-unit id="Share one-time invitation link" xml:space="preserve"> - <source>Share one-time invitation link</source> - <target>Jednorázový zvací odkaz</target> + <trans-unit id="Share this 1-time invite link" xml:space="preserve"> + <source>Share this 1-time invite link</source> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="Share with contacts" xml:space="preserve"> @@ -4697,16 +4823,15 @@ This is your link for group %@!</source> <target>Někdo</target> <note>notification title</note> </trans-unit> - <trans-unit id="Start a new chat" xml:space="preserve"> - <source>Start a new chat</source> - <target>Začít nový chat</target> - <note>No comment provided by engineer.</note> - </trans-unit> <trans-unit id="Start chat" xml:space="preserve"> <source>Start chat</source> <target>Začít chat</target> <note>No comment provided by engineer.</note> </trans-unit> + <trans-unit id="Start chat?" xml:space="preserve"> + <source>Start chat?</source> + <note>No comment provided by engineer.</note> + </trans-unit> <trans-unit id="Start migration" xml:space="preserve"> <source>Start migration</source> <target>Zahájit přenesení</target> @@ -4831,6 +4956,14 @@ This is your link for group %@!</source> <target>Klepnutím se připojíte inkognito</target> <note>No comment provided by engineer.</note> </trans-unit> + <trans-unit id="Tap to paste link" xml:space="preserve"> + <source>Tap to paste link</source> + <note>No comment provided by engineer.</note> + </trans-unit> + <trans-unit id="Tap to scan" xml:space="preserve"> + <source>Tap to scan</source> + <note>No comment provided by engineer.</note> + </trans-unit> <trans-unit id="Tap to start a new chat" xml:space="preserve"> <source>Tap to start a new chat</source> <target>Klepnutím na zahájíte nový chat</target> @@ -4893,6 +5026,10 @@ Může se to stát kvůli nějaké chybě, nebo pokud je spojení kompromitován <target>Pokus o změnu přístupové fráze databáze nebyl dokončen.</target> <note>No comment provided by engineer.</note> </trans-unit> + <trans-unit id="The code you scanned is not a SimpleX link QR code." xml:space="preserve"> + <source>The code you scanned is not a SimpleX link QR code.</source> + <note>No comment provided by engineer.</note> + </trans-unit> <trans-unit id="The connection you accepted will be cancelled!" xml:space="preserve"> <source>The connection you accepted will be cancelled!</source> <target>Připojení, které jste přijali, bude zrušeno!</target> @@ -4958,21 +5095,15 @@ Může se to stát kvůli nějaké chybě, nebo pokud je spojení kompromitován <target>Servery pro nová připojení vašeho aktuálního chat profilu **%@**.</target> <note>No comment provided by engineer.</note> </trans-unit> + <trans-unit id="The text you pasted is not a SimpleX link." xml:space="preserve"> + <source>The text you pasted is not a SimpleX link.</source> + <note>No comment provided by engineer.</note> + </trans-unit> <trans-unit id="Theme" xml:space="preserve"> <source>Theme</source> <target>Téma</target> <note>No comment provided by engineer.</note> </trans-unit> - <trans-unit id="There should be at least one user profile." xml:space="preserve"> - <source>There should be at least one user profile.</source> - <target>Měl by tam být alespoň jeden uživatelský profil.</target> - <note>No comment provided by engineer.</note> - </trans-unit> - <trans-unit id="There should be at least one visible user profile." xml:space="preserve"> - <source>There should be at least one visible user profile.</source> - <target>Měl by tam být alespoň jeden viditelný uživatelský profil.</target> - <note>No comment provided by engineer.</note> - </trans-unit> <trans-unit id="These settings are for your current profile **%@**." xml:space="preserve"> <source>These settings are for your current profile **%@**.</source> <target>Toto nastavení je pro váš aktuální profil **%@**.</target> @@ -5002,6 +5133,10 @@ Může se to stát kvůli nějaké chybě, nebo pokud je spojení kompromitován <source>This device name</source> <note>No comment provided by engineer.</note> </trans-unit> + <trans-unit id="This display name is invalid. Please choose another name." xml:space="preserve"> + <source>This display name is invalid. Please choose another name.</source> + <note>No comment provided by engineer.</note> + </trans-unit> <trans-unit id="This group has over %lld members, delivery receipts are not sent." xml:space="preserve"> <source>This group has over %lld members, delivery receipts are not sent.</source> <target>Tato skupina má více než %lld členů, potvrzení o doručení nejsou odesílány.</target> @@ -5101,16 +5236,15 @@ Před zapnutím této funkce budete vyzváni k dokončení ověření.</target> <target>Pokus o připojení k serveru používanému pro příjem zpráv od tohoto kontaktu.</target> <note>No comment provided by engineer.</note> </trans-unit> + <trans-unit id="Turkish interface" xml:space="preserve"> + <source>Turkish interface</source> + <note>No comment provided by engineer.</note> + </trans-unit> <trans-unit id="Turn off" xml:space="preserve"> <source>Turn off</source> <target>Vypnout</target> <note>No comment provided by engineer.</note> </trans-unit> - <trans-unit id="Turn off notifications?" xml:space="preserve"> - <source>Turn off notifications?</source> - <target>Vypnout upozornění?</target> - <note>No comment provided by engineer.</note> - </trans-unit> <trans-unit id="Turn on" xml:space="preserve"> <source>Turn on</source> <target>Zapnout</target> @@ -5125,10 +5259,18 @@ Před zapnutím této funkce budete vyzváni k dokončení ověření.</target> <source>Unblock</source> <note>No comment provided by engineer.</note> </trans-unit> + <trans-unit id="Unblock for all" xml:space="preserve"> + <source>Unblock for all</source> + <note>No comment provided by engineer.</note> + </trans-unit> <trans-unit id="Unblock member" xml:space="preserve"> <source>Unblock member</source> <note>No comment provided by engineer.</note> </trans-unit> + <trans-unit id="Unblock member for all?" xml:space="preserve"> + <source>Unblock member for all?</source> + <note>No comment provided by engineer.</note> + </trans-unit> <trans-unit id="Unblock member?" xml:space="preserve"> <source>Unblock member?</source> <note>No comment provided by engineer.</note> @@ -5223,6 +5365,10 @@ Chcete-li se připojit, požádejte svůj kontakt o vytvoření dalšího odkazu <target>Nepřečtený</target> <note>No comment provided by engineer.</note> </trans-unit> + <trans-unit id="Up to 100 last messages are sent to new members." xml:space="preserve"> + <source>Up to 100 last messages are sent to new members.</source> + <note>No comment provided by engineer.</note> + </trans-unit> <trans-unit id="Update" xml:space="preserve"> <source>Update</source> <target>Aktualizovat</target> @@ -5307,6 +5453,10 @@ Chcete-li se připojit, požádejte svůj kontakt o vytvoření dalšího odkazu <target>Použít nový inkognito profil</target> <note>No comment provided by engineer.</note> </trans-unit> + <trans-unit id="Use only local notifications?" xml:space="preserve"> + <source>Use only local notifications?</source> + <note>No comment provided by engineer.</note> + </trans-unit> <trans-unit id="Use server" xml:space="preserve"> <source>Use server</source> <target>Použít server</target> @@ -5383,6 +5533,10 @@ Chcete-li se připojit, požádejte svůj kontakt o vytvoření dalšího odkazu <target>Zobrazení bezpečnostního kódu</target> <note>No comment provided by engineer.</note> </trans-unit> + <trans-unit id="Visible history" xml:space="preserve"> + <source>Visible history</source> + <note>chat feature</note> + </trans-unit> <trans-unit id="Voice messages" xml:space="preserve"> <source>Voice messages</source> <target>Hlasové zprávy</target> @@ -5467,11 +5621,19 @@ Chcete-li se připojit, požádejte svůj kontakt o vytvoření dalšího odkazu <target>Pokud s někým sdílíte inkognito profil, bude tento profil použit pro skupiny, do kterých vás pozve.</target> <note>No comment provided by engineer.</note> </trans-unit> + <trans-unit id="With encrypted files and media." xml:space="preserve"> + <source>With encrypted files and media.</source> + <note>No comment provided by engineer.</note> + </trans-unit> <trans-unit id="With optional welcome message." xml:space="preserve"> <source>With optional welcome message.</source> <target>S volitelnou uvítací zprávou.</target> <note>No comment provided by engineer.</note> </trans-unit> + <trans-unit id="With reduced battery usage." xml:space="preserve"> + <source>With reduced battery usage.</source> + <note>No comment provided by engineer.</note> + </trans-unit> <trans-unit id="Wrong database passphrase" xml:space="preserve"> <source>Wrong database passphrase</source> <target>Špatná přístupová fráze k databázi</target> @@ -5556,11 +5718,6 @@ Repeat join request?</source> <target>Můžete přijímat hovory z obrazovky zámku, bez ověření zařízení a aplikace.</target> <note>No comment provided by engineer.</note> </trans-unit> - <trans-unit id="You can also connect by clicking the link. If it opens in the browser, click **Open in mobile app** button." xml:space="preserve"> - <source>You can also connect by clicking the link. If it opens in the browser, click **Open in mobile app** button.</source> - <target>Můžete se také připojit kliknutím na odkaz. Pokud se otevře v prohlížeči, klikněte na tlačítko **Otevřít v mobilní aplikaci**.</target> - <note>No comment provided by engineer.</note> - </trans-unit> <trans-unit id="You can create it later" xml:space="preserve"> <source>You can create it later</source> <target>Můžete vytvořit později</target> @@ -5581,6 +5738,10 @@ Repeat join request?</source> <target>Profil uživatele můžete skrýt nebo ztlumit - přejeďte prstem doprava.</target> <note>No comment provided by engineer.</note> </trans-unit> + <trans-unit id="You can make it visible to your SimpleX contacts via Settings." xml:space="preserve"> + <source>You can make it visible to your SimpleX contacts via Settings.</source> + <note>No comment provided by engineer.</note> + </trans-unit> <trans-unit id="You can now send messages to %@" xml:space="preserve"> <source>You can now send messages to %@</source> <target>Nyní můžete posílat zprávy %@</target> @@ -5621,6 +5782,10 @@ Repeat join request?</source> <target>K formátování zpráv můžete použít markdown:</target> <note>No comment provided by engineer.</note> </trans-unit> + <trans-unit id="You can view invitation link again in connection details." xml:space="preserve"> + <source>You can view invitation link again in connection details.</source> + <note>No comment provided by engineer.</note> + </trans-unit> <trans-unit id="You can't send messages!" xml:space="preserve"> <source>You can't send messages!</source> <target>Nemůžete posílat zprávy!</target> @@ -5805,13 +5970,6 @@ Toto připojení můžete zrušit a kontakt odebrat (a zkusit to později s nov <target>Vaše kontakty mohou povolit úplné mazání zpráv.</target> <note>No comment provided by engineer.</note> </trans-unit> - <trans-unit id="Your contacts in SimpleX will see it. You can change it in Settings." xml:space="preserve"> - <source>Your contacts in SimpleX will see it. -You can change it in Settings.</source> - <target>Vaše kontakty v SimpleX ji uvidí. -Můžete ji změnit v Nastavení.</target> - <note>No comment provided by engineer.</note> - </trans-unit> <trans-unit id="Your contacts will remain connected." xml:space="preserve"> <source>Your contacts will remain connected.</source> <target>Vaše kontakty zůstanou připojeny.</target> @@ -5960,6 +6118,14 @@ Servery SimpleX nevidí váš profil.</target> <source>blocked</source> <note>No comment provided by engineer.</note> </trans-unit> + <trans-unit id="blocked %@" xml:space="preserve"> + <source>blocked %@</source> + <note>rcv group event chat item</note> + </trans-unit> + <trans-unit id="blocked by admin" xml:space="preserve"> + <source>blocked by admin</source> + <note>blocked chat item</note> + </trans-unit> <trans-unit id="bold" xml:space="preserve"> <source>bold</source> <target>tučně</target> @@ -6080,6 +6246,10 @@ Servery SimpleX nevidí váš profil.</target> <target>připojení:%@</target> <note>connection information</note> </trans-unit> + <trans-unit id="contact %@ changed to %@" xml:space="preserve"> + <source>contact %1$@ changed to %2$@</source> + <note>profile update event chat item</note> + </trans-unit> <trans-unit id="contact has e2e encryption" xml:space="preserve"> <source>contact has e2e encryption</source> <target>kontakt má šifrování e2e</target> @@ -6348,6 +6518,10 @@ Servery SimpleX nevidí váš profil.</target> <target>člen</target> <note>member role</note> </trans-unit> + <trans-unit id="member %@ changed to %@" xml:space="preserve"> + <source>member %1$@ changed to %2$@</source> + <note>profile update event chat item</note> + </trans-unit> <trans-unit id="member connected" xml:space="preserve"> <source>connected</source> <target>připojeno</target> @@ -6470,6 +6644,14 @@ Servery SimpleX nevidí váš profil.</target> <target>odstraněno %@</target> <note>rcv group event chat item</note> </trans-unit> + <trans-unit id="removed contact address" xml:space="preserve"> + <source>removed contact address</source> + <note>profile update event chat item</note> + </trans-unit> + <trans-unit id="removed profile picture" xml:space="preserve"> + <source>removed profile picture</source> + <note>profile update event chat item</note> + </trans-unit> <trans-unit id="removed you" xml:space="preserve"> <source>removed you</source> <target>odstranil vás</target> @@ -6500,6 +6682,14 @@ Servery SimpleX nevidí váš profil.</target> <target>odeslat přímou zprávu</target> <note>No comment provided by engineer.</note> </trans-unit> + <trans-unit id="set new contact address" xml:space="preserve"> + <source>set new contact address</source> + <note>profile update event chat item</note> + </trans-unit> + <trans-unit id="set new profile picture" xml:space="preserve"> + <source>set new profile picture</source> + <note>profile update event chat item</note> + </trans-unit> <trans-unit id="starting…" xml:space="preserve"> <source>starting…</source> <target>začíná…</target> @@ -6515,16 +6705,28 @@ Servery SimpleX nevidí váš profil.</target> <target>tento kontakt</target> <note>notification title</note> </trans-unit> + <trans-unit id="unblocked %@" xml:space="preserve"> + <source>unblocked %@</source> + <note>rcv group event chat item</note> + </trans-unit> <trans-unit id="unknown" xml:space="preserve"> <source>unknown</source> <target>neznámý</target> <note>connection info</note> </trans-unit> + <trans-unit id="unknown status" xml:space="preserve"> + <source>unknown status</source> + <note>No comment provided by engineer.</note> + </trans-unit> <trans-unit id="updated group profile" xml:space="preserve"> <source>updated group profile</source> <target>aktualizoval profil skupiny</target> <note>rcv group event chat item</note> </trans-unit> + <trans-unit id="updated profile" xml:space="preserve"> + <source>updated profile</source> + <note>profile update event chat item</note> + </trans-unit> <trans-unit id="v%@" xml:space="preserve"> <source>v%@</source> <note>No comment provided by engineer.</note> @@ -6594,6 +6796,10 @@ Servery SimpleX nevidí váš profil.</target> <target>jste pozorovatel</target> <note>No comment provided by engineer.</note> </trans-unit> + <trans-unit id="you blocked %@" xml:space="preserve"> + <source>you blocked %@</source> + <note>snd group event chat item</note> + </trans-unit> <trans-unit id="you changed address" xml:space="preserve"> <source>you changed address</source> <target>změnili jste adresu</target> @@ -6634,6 +6840,10 @@ Servery SimpleX nevidí váš profil.</target> <target>sdíleli jste jednorázový odkaz inkognito</target> <note>chat list item description</note> </trans-unit> + <trans-unit id="you unblocked %@" xml:space="preserve"> + <source>you unblocked %@</source> + <note>snd group event chat item</note> + </trans-unit> <trans-unit id="you: " xml:space="preserve"> <source>you: </source> <target>vy: </target> diff --git a/apps/ios/SimpleX Localizations/de.xcloc/Localized Contents/de.xliff b/apps/ios/SimpleX Localizations/de.xcloc/Localized Contents/de.xliff index 75f70f7ad1..d0f217a0e1 100644 --- a/apps/ios/SimpleX Localizations/de.xcloc/Localized Contents/de.xliff +++ b/apps/ios/SimpleX Localizations/de.xcloc/Localized Contents/de.xliff @@ -49,7 +49,7 @@ </trans-unit> <trans-unit id="## History" xml:space="preserve"> <source>## History</source> - <target>## Vergangenheit</target> + <target>## Nachrichtenverlauf</target> <note>copied message info</note> </trans-unit> <trans-unit id="## In reply to" xml:space="preserve"> @@ -217,6 +217,11 @@ <target>%lld Nachrichten blockiert</target> <note>No comment provided by engineer.</note> </trans-unit> + <trans-unit id="%lld messages blocked by admin" xml:space="preserve"> + <source>%lld messages blocked by admin</source> + <target>%lld Nachrichten wurden vom Administrator blockiert</target> + <note>No comment provided by engineer.</note> + </trans-unit> <trans-unit id="%lld messages marked deleted" xml:space="preserve"> <source>%lld messages marked deleted</source> <target>%lld Nachrichten als gelöscht markiert</target> @@ -312,14 +317,19 @@ <target>)</target> <note>No comment provided by engineer.</note> </trans-unit> - <trans-unit id="**Add new contact**: to create your one-time QR Code for your contact." xml:space="preserve"> - <source>**Add new contact**: to create your one-time QR Code or link for your contact.</source> - <target>**Fügen Sie einen neuen Kontakt hinzu**: Erzeugen Sie einen Einmal-QR-Code oder -Link für Ihren Kontakt.</target> + <trans-unit id="**Add contact**: to create a new invitation link, or connect via a link you received." xml:space="preserve"> + <source>**Add contact**: to create a new invitation link, or connect via a link you received.</source> + <target>**Kontakt hinzufügen**: Um einen neuen Einladungslink zu erstellen oder eine Verbindung über einen Link herzustellen, den Sie erhalten haben.</target> <note>No comment provided by engineer.</note> </trans-unit> - <trans-unit id="**Create link / QR code** for your contact to use." xml:space="preserve"> - <source>**Create link / QR code** for your contact to use.</source> - <target>**Generieren Sie einen Einladungs-Link / QR code** für Ihren Kontakt.</target> + <trans-unit id="**Add new contact**: to create your one-time QR Code for your contact." xml:space="preserve"> + <source>**Add new contact**: to create your one-time QR Code or link for your contact.</source> + <target>**Neuen Kontakt hinzufügen**: Um einen Einmal-QR-Code oder -Link für Ihren Kontakt zu erzeugen.</target> + <note>No comment provided by engineer.</note> + </trans-unit> + <trans-unit id="**Create group**: to create a new group." xml:space="preserve"> + <source>**Create group**: to create a new group.</source> + <target>**Gruppe erstellen**: Um eine neue Gruppe zu erstellen.</target> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="**More private**: check new messages every 20 minutes. Device token is shared with SimpleX Chat server, but not how many contacts or messages you have." xml:space="preserve"> @@ -332,11 +342,6 @@ <target>**Beste Privatsphäre**: Es wird kein SimpleX-Chat-Benachrichtigungs-Server genutzt, Nachrichten werden in periodischen Abständen im Hintergrund geprüft (dies hängt davon ab, wie häufig Sie die App nutzen).</target> <note>No comment provided by engineer.</note> </trans-unit> - <trans-unit id="**Paste received link** or open it in the browser and tap **Open in mobile app**." xml:space="preserve"> - <source>**Paste received link** or open it in the browser and tap **Open in mobile app**.</source> - <target>**Fügen Sie den von Ihrem Kontakt erhaltenen Link ein** oder öffnen Sie ihn im Browser und tippen Sie auf **In mobiler App öffnen**.</target> - <note>No comment provided by engineer.</note> - </trans-unit> <trans-unit id="**Please note**: you will NOT be able to recover or change passphrase if you lose it." xml:space="preserve"> <source>**Please note**: you will NOT be able to recover or change passphrase if you lose it.</source> <target>**Bitte beachten Sie**: Das Passwort kann NICHT wiederhergestellt oder geändert werden, wenn Sie es vergessen haben oder verlieren.</target> @@ -347,11 +352,6 @@ <target>**Empfohlen**: Nur Ihr Geräte-Token und ihre Benachrichtigungen werden an den SimpleX-Chat-Benachrichtigungs-Server gesendet, aber weder der Nachrichteninhalt noch deren Größe oder von wem sie gesendet wurde.</target> <note>No comment provided by engineer.</note> </trans-unit> - <trans-unit id="**Scan QR code**: to connect to your contact in person or via video call." xml:space="preserve"> - <source>**Scan QR code**: to connect to your contact in person or via video call.</source> - <target>**Scannen Sie den QR-Code**, um sich während einem persönlichen Treffen oder per Videoanruf mit Ihrem Kontakt zu verbinden.</target> - <note>No comment provided by engineer.</note> - </trans-unit> <trans-unit id="**Warning**: Instant push notifications require passphrase saved in Keychain." xml:space="preserve"> <source>**Warning**: Instant push notifications require passphrase saved in Keychain.</source> <target>**Warnung**: Sofortige Push-Benachrichtigungen erfordern die Eingabe eines Passworts, welches in Ihrem Schlüsselbund gespeichert ist.</target> @@ -408,9 +408,9 @@ <source>- voice messages up to 5 minutes. - custom time to disappear. - editing history.</source> - <target>- Bis zu 5 Minuten lange Sprachnachrichten. -- Zeitdauer für verschwindende Nachrichten anpassen. -- Nachrichten-Historie bearbeiten.</target> + <target>- Bis zu 5 Minuten lange Sprachnachrichten +- Zeitdauer für verschwindende Nachrichten anpassen +- Nachrichtenverlauf bearbeiten</target> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="." xml:space="preserve"> @@ -453,11 +453,6 @@ <target>wöchentlich</target> <note>time interval</note> </trans-unit> - <trans-unit id="1-time link" xml:space="preserve"> - <source>1-time link</source> - <target>Einmal-Link</target> - <note>No comment provided by engineer.</note> - </trans-unit> <trans-unit id="5 minutes" xml:space="preserve"> <source>5 minutes</source> <target>5 Minuten</target> @@ -519,12 +514,12 @@ </trans-unit> <trans-unit id="Abort changing address" xml:space="preserve"> <source>Abort changing address</source> - <target>Wechsel der Adresse abbrechen</target> + <target>Wechsel der Empfängeradresse abbrechen</target> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="Abort changing address?" xml:space="preserve"> <source>Abort changing address?</source> - <target>Wechsel der Adresse abbrechen?</target> + <target>Wechsel der Empfängeradresse abbrechen?</target> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="About SimpleX" xml:space="preserve"> @@ -570,7 +565,12 @@ </trans-unit> <trans-unit id="Add address to your profile, so that your contacts can share it with other people. Profile update will be sent to your contacts." xml:space="preserve"> <source>Add address to your profile, so that your contacts can share it with other people. Profile update will be sent to your contacts.</source> - <target>Fügen Sie die Adresse zu Ihrem Profil hinzu, damit Ihre Kontakte sie mit anderen Personen teilen können. Es wird eine Profilaktualisierung an Ihre Kontakte gesendet.</target> + <target>Fügen Sie die Adresse Ihrem Profil hinzu, damit Ihre Kontakte sie mit anderen Personen teilen können. Es wird eine Profilaktualisierung an Ihre Kontakte gesendet.</target> + <note>No comment provided by engineer.</note> + </trans-unit> + <trans-unit id="Add contact" xml:space="preserve"> + <source>Add contact</source> + <target>Kontakt hinzufügen</target> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="Add preset servers" xml:space="preserve"> @@ -610,7 +610,7 @@ </trans-unit> <trans-unit id="Address change will be aborted. Old receiving address will be used." xml:space="preserve"> <source>Address change will be aborted. Old receiving address will be used.</source> - <target>Der Wechsel der Adresse wird abgebrochen. Die bisherige Adresse wird weiter verwendet.</target> + <target>Der Wechsel der Empfängeradresse wird abgebrochen. Die bisherige Adresse wird weiter verwendet.</target> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="Admins can create the links to join groups." xml:space="preserve"> @@ -643,6 +643,11 @@ <target>Alle Gruppenmitglieder bleiben verbunden.</target> <note>No comment provided by engineer.</note> </trans-unit> + <trans-unit id="All messages will be deleted - this cannot be undone!" xml:space="preserve"> + <source>All messages will be deleted - this cannot be undone!</source> + <target>Es werden alle Nachrichten gelöscht. Dieser Vorgang kann nicht rückgängig gemacht werden!</target> + <note>No comment provided by engineer.</note> + </trans-unit> <trans-unit id="All messages will be deleted - this cannot be undone! The messages will be deleted ONLY for you." xml:space="preserve"> <source>All messages will be deleted - this cannot be undone! The messages will be deleted ONLY for you.</source> <target>Alle Nachrichten werden gelöscht - dies kann nicht rückgängig gemacht werden! Die Nachrichten werden NUR bei Ihnen gelöscht.</target> @@ -650,7 +655,7 @@ </trans-unit> <trans-unit id="All new messages from %@ will be hidden!" xml:space="preserve"> <source>All new messages from %@ will be hidden!</source> - <target>Alle neuen Nachrichten von %@ werden verborgen!</target> + <target>Von %@ werden alle neuen Nachrichten ausgeblendet!</target> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="All your contacts will remain connected." xml:space="preserve"> @@ -675,12 +680,12 @@ </trans-unit> <trans-unit id="Allow disappearing messages only if your contact allows it to you." xml:space="preserve"> <source>Allow disappearing messages only if your contact allows it to you.</source> - <target>Erlauben Sie verschwindende Nachrichten nur dann, wenn es Ihnen Ihr Kontakt ebenfalls erlaubt.</target> + <target>Erlauben Sie verschwindende Nachrichten nur dann, wenn es Ihr Kontakt ebenfalls erlaubt.</target> <note>No comment provided by engineer.</note> </trans-unit> - <trans-unit id="Allow irreversible message deletion only if your contact allows it to you." xml:space="preserve"> - <source>Allow irreversible message deletion only if your contact allows it to you.</source> - <target>Erlauben Sie das unwiederbringliche Löschen von Nachrichten nur dann, wenn es Ihnen Ihr Kontakt ebenfalls erlaubt.</target> + <trans-unit id="Allow irreversible message deletion only if your contact allows it to you. (24 hours)" xml:space="preserve"> + <source>Allow irreversible message deletion only if your contact allows it to you. (24 hours)</source> + <target>Erlauben Sie das unwiederbringliche Löschen von Nachrichten nur dann, wenn es Ihnen Ihr Kontakt ebenfalls erlaubt. (24 Stunden)</target> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="Allow message reactions only if your contact allows them." xml:space="preserve"> @@ -703,9 +708,9 @@ <target>Das Senden von verschwindenden Nachrichten erlauben.</target> <note>No comment provided by engineer.</note> </trans-unit> - <trans-unit id="Allow to irreversibly delete sent messages." xml:space="preserve"> - <source>Allow to irreversibly delete sent messages.</source> - <target>Unwiederbringliches löschen von gesendeten Nachrichten erlauben.</target> + <trans-unit id="Allow to irreversibly delete sent messages. (24 hours)" xml:space="preserve"> + <source>Allow to irreversibly delete sent messages. (24 hours)</source> + <target>Unwiederbringliches löschen von gesendeten Nachrichten erlauben. (24 Stunden)</target> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="Allow to send files and media." xml:space="preserve"> @@ -738,9 +743,9 @@ <target>Erlaubt Ihren Kontakten Sie anzurufen.</target> <note>No comment provided by engineer.</note> </trans-unit> - <trans-unit id="Allow your contacts to irreversibly delete sent messages." xml:space="preserve"> - <source>Allow your contacts to irreversibly delete sent messages.</source> - <target>Erlauben Sie Ihren Kontakten gesendete Nachrichten unwiederbringlich zu löschen.</target> + <trans-unit id="Allow your contacts to irreversibly delete sent messages. (24 hours)" xml:space="preserve"> + <source>Allow your contacts to irreversibly delete sent messages. (24 hours)</source> + <target>Erlauben Sie Ihren Kontakten gesendete Nachrichten unwiederbringlich zu löschen. (24 Stunden)</target> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="Allow your contacts to send disappearing messages." xml:space="preserve"> @@ -918,6 +923,11 @@ <target>Blockieren</target> <note>No comment provided by engineer.</note> </trans-unit> + <trans-unit id="Block for all" xml:space="preserve"> + <source>Block for all</source> + <target>Für Alle blockieren</target> + <note>No comment provided by engineer.</note> + </trans-unit> <trans-unit id="Block group members" xml:space="preserve"> <source>Block group members</source> <target>Gruppenmitglieder blockieren</target> @@ -928,19 +938,29 @@ <target>Mitglied blockieren</target> <note>No comment provided by engineer.</note> </trans-unit> + <trans-unit id="Block member for all?" xml:space="preserve"> + <source>Block member for all?</source> + <target>Mitglied für Alle blockieren?</target> + <note>No comment provided by engineer.</note> + </trans-unit> <trans-unit id="Block member?" xml:space="preserve"> <source>Block member?</source> <target>Mitglied blockieren?</target> <note>No comment provided by engineer.</note> </trans-unit> + <trans-unit id="Blocked by admin" xml:space="preserve"> + <source>Blocked by admin</source> + <target>wurde vom Administrator blockiert</target> + <note>No comment provided by engineer.</note> + </trans-unit> <trans-unit id="Both you and your contact can add message reactions." xml:space="preserve"> <source>Both you and your contact can add message reactions.</source> <target>Sowohl Sie, als auch Ihr Kontakt können Reaktionen auf Nachrichten geben.</target> <note>No comment provided by engineer.</note> </trans-unit> - <trans-unit id="Both you and your contact can irreversibly delete sent messages." xml:space="preserve"> - <source>Both you and your contact can irreversibly delete sent messages.</source> - <target>Sowohl Ihr Kontakt, als auch Sie können gesendete Nachrichten unwiederbringlich löschen.</target> + <trans-unit id="Both you and your contact can irreversibly delete sent messages. (24 hours)" xml:space="preserve"> + <source>Both you and your contact can irreversibly delete sent messages. (24 hours)</source> + <target>Sowohl Ihr Kontakt, als auch Sie können gesendete Nachrichten unwiederbringlich löschen. (24 Stunden)</target> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="Both you and your contact can make calls." xml:space="preserve"> @@ -978,9 +998,9 @@ <target>Anrufe</target> <note>No comment provided by engineer.</note> </trans-unit> - <trans-unit id="Can't delete user profile!" xml:space="preserve"> - <source>Can't delete user profile!</source> - <target>Das Benutzerprofil kann nicht gelöscht werden!</target> + <trans-unit id="Camera not available" xml:space="preserve"> + <source>Camera not available</source> + <target>Kamera nicht verfügbar</target> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="Can't invite contact!" xml:space="preserve"> @@ -1094,6 +1114,11 @@ <target>Der Chat ist beendet</target> <note>No comment provided by engineer.</note> </trans-unit> + <trans-unit id="Chat is stopped. If you already used this database on another device, you should transfer it back before starting chat." xml:space="preserve"> + <source>Chat is stopped. If you already used this database on another device, you should transfer it back before starting chat.</source> + <target>Der Chat ist angehalten. Wenn Sie diese Datenbank bereits auf einem anderen Gerät genutzt haben, sollten Sie diese vor dem Starten des Chats wieder zurückspielen.</target> + <note>No comment provided by engineer.</note> + </trans-unit> <trans-unit id="Chat preferences" xml:space="preserve"> <source>Chat preferences</source> <target>Chat-Präferenzen</target> @@ -1139,6 +1164,11 @@ <target>Unterhaltung löschen?</target> <note>No comment provided by engineer.</note> </trans-unit> + <trans-unit id="Clear private notes?" xml:space="preserve"> + <source>Clear private notes?</source> + <target>Private Notizen löschen?</target> + <note>No comment provided by engineer.</note> + </trans-unit> <trans-unit id="Clear verification" xml:space="preserve"> <source>Clear verification</source> <target>Überprüfung zurücknehmen</target> @@ -1217,7 +1247,7 @@ <trans-unit id="Connect to yourself? This is your own SimpleX address!" xml:space="preserve"> <source>Connect to yourself? This is your own SimpleX address!</source> - <target>Mit Ihnen selbst verbinden? + <target>Sich mit Ihnen selbst verbinden? Das ist Ihre eigene SimpleX-Adresse!</target> <note>No comment provided by engineer.</note> </trans-unit> @@ -1238,11 +1268,6 @@ Das ist Ihr eigener Einmal-Link!</target> <target>Über einen Link verbinden</target> <note>No comment provided by engineer.</note> </trans-unit> - <trans-unit id="Connect via link / QR code" xml:space="preserve"> - <source>Connect via link / QR code</source> - <target>Über einen Link / QR-Code verbinden</target> - <note>No comment provided by engineer.</note> - </trans-unit> <trans-unit id="Connect via one-time link" xml:space="preserve"> <source>Connect via one-time link</source> <target>Über einen Einmal-Link verbinden</target> @@ -1418,11 +1443,6 @@ Das ist Ihr eigener Einmal-Link!</target> <target>Neues Profil in der [Desktop-App] erstellen (https://simplex.chat/downloads/). 💻</target> <note>No comment provided by engineer.</note> </trans-unit> - <trans-unit id="Create one-time invitation link" xml:space="preserve"> - <source>Create one-time invitation link</source> - <target>Einmal-Einladungslink erstellen</target> - <note>No comment provided by engineer.</note> - </trans-unit> <trans-unit id="Create profile" xml:space="preserve"> <source>Create profile</source> <target>Profil erstellen</target> @@ -1443,11 +1463,26 @@ Das ist Ihr eigener Einmal-Link!</target> <target>Erstellen Sie Ihr Profil</target> <note>No comment provided by engineer.</note> </trans-unit> + <trans-unit id="Created at" xml:space="preserve"> + <source>Created at</source> + <target>Erstellt um</target> + <note>No comment provided by engineer.</note> + </trans-unit> + <trans-unit id="Created at: %@" xml:space="preserve"> + <source>Created at: %@</source> + <target>Erstellt um: %@</target> + <note>copied message info</note> + </trans-unit> <trans-unit id="Created on %@" xml:space="preserve"> <source>Created on %@</source> <target>Erstellt am %@</target> <note>No comment provided by engineer.</note> </trans-unit> + <trans-unit id="Creating link…" xml:space="preserve"> + <source>Creating link…</source> + <target>Link wird erstellt…</target> + <note>No comment provided by engineer.</note> + </trans-unit> <trans-unit id="Current Passcode" xml:space="preserve"> <source>Current Passcode</source> <target>Aktueller Zugangscode</target> @@ -1875,7 +1910,7 @@ Das kann nicht rückgängig gemacht werden!</target> </trans-unit> <trans-unit id="Disappearing messages" xml:space="preserve"> <source>Disappearing messages</source> - <target>verschwindende Nachrichten</target> + <target>Verschwindende Nachrichten</target> <note>chat feature</note> </trans-unit> <trans-unit id="Disappearing messages are prohibited in this chat." xml:space="preserve"> @@ -1928,6 +1963,11 @@ Das kann nicht rückgängig gemacht werden!</target> <target>Später wiederholen</target> <note>No comment provided by engineer.</note> </trans-unit> + <trans-unit id="Do not send history to new members." xml:space="preserve"> + <source>Do not send history to new members.</source> + <target>Den Nachrichtenverlauf nicht an neue Mitglieder senden.</target> + <note>No comment provided by engineer.</note> + </trans-unit> <trans-unit id="Don't create address" xml:space="preserve"> <source>Don't create address</source> <target>Keine Adresse erstellt</target> @@ -1998,6 +2038,11 @@ Das kann nicht rückgängig gemacht werden!</target> <target>Automatisches Löschen von Nachrichten aktivieren?</target> <note>No comment provided by engineer.</note> </trans-unit> + <trans-unit id="Enable camera access" xml:space="preserve"> + <source>Enable camera access</source> + <target>Kamera-Zugriff aktivieren</target> + <note>No comment provided by engineer.</note> + </trans-unit> <trans-unit id="Enable for all" xml:space="preserve"> <source>Enable for all</source> <target>Für Alle aktivieren</target> @@ -2063,6 +2108,11 @@ Das kann nicht rückgängig gemacht werden!</target> <target>Verschlüsselte Nachricht oder ein anderes Ereignis</target> <note>notification</note> </trans-unit> + <trans-unit id="Encrypted message: app is stopped" xml:space="preserve"> + <source>Encrypted message: app is stopped</source> + <target>Verschlüsselte Nachricht: Die App ist angehalten</target> + <note>notification</note> + </trans-unit> <trans-unit id="Encrypted message: database error" xml:space="preserve"> <source>Encrypted message: database error</source> <target>Verschlüsselte Nachricht: Datenbankfehler</target> @@ -2175,7 +2225,7 @@ Das kann nicht rückgängig gemacht werden!</target> </trans-unit> <trans-unit id="Error changing address" xml:space="preserve"> <source>Error changing address</source> - <target>Fehler beim Wechseln der Adresse</target> + <target>Fehler beim Wechseln der Empfängeradresse</target> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="Error changing role" xml:space="preserve"> @@ -2208,6 +2258,11 @@ Das kann nicht rückgängig gemacht werden!</target> <target>Fehler beim Anlegen eines Mitglied-Kontaktes</target> <note>No comment provided by engineer.</note> </trans-unit> + <trans-unit id="Error creating message" xml:space="preserve"> + <source>Error creating message</source> + <target>Fehler beim Erstellen der Nachricht</target> + <note>No comment provided by engineer.</note> + </trans-unit> <trans-unit id="Error creating profile!" xml:space="preserve"> <source>Error creating profile!</source> <target>Fehler beim Erstellen des Profils!</target> @@ -2293,6 +2348,11 @@ Das kann nicht rückgängig gemacht werden!</target> <target>Fehler beim Laden von %@ Servern</target> <note>No comment provided by engineer.</note> </trans-unit> + <trans-unit id="Error opening chat" xml:space="preserve"> + <source>Error opening chat</source> + <target>Fehler beim Öffnen des Chats</target> + <note>No comment provided by engineer.</note> + </trans-unit> <trans-unit id="Error receiving file" xml:space="preserve"> <source>Error receiving file</source> <target>Fehler beim Empfangen der Datei</target> @@ -2333,6 +2393,11 @@ Das kann nicht rückgängig gemacht werden!</target> <target>Fehler beim Speichern des Benutzer-Passworts</target> <note>No comment provided by engineer.</note> </trans-unit> + <trans-unit id="Error scanning code: %@" xml:space="preserve"> + <source>Error scanning code: %@</source> + <target>Fehler beim Scannen des Codes: %@</target> + <note>No comment provided by engineer.</note> + </trans-unit> <trans-unit id="Error sending email" xml:space="preserve"> <source>Error sending email</source> <target>Fehler beim Senden der eMail</target> @@ -2663,9 +2728,9 @@ Das kann nicht rückgängig gemacht werden!</target> <target>Gruppenmitglieder können eine Reaktion auf Nachrichten geben.</target> <note>No comment provided by engineer.</note> </trans-unit> - <trans-unit id="Group members can irreversibly delete sent messages." xml:space="preserve"> - <source>Group members can irreversibly delete sent messages.</source> - <target>Gruppenmitglieder können gesendete Nachrichten unwiederbringlich löschen.</target> + <trans-unit id="Group members can irreversibly delete sent messages. (24 hours)" xml:space="preserve"> + <source>Group members can irreversibly delete sent messages. (24 hours)</source> + <target>Gruppenmitglieder können gesendete Nachrichten unwiederbringlich löschen. (24 Stunden)</target> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="Group members can send direct messages." xml:space="preserve"> @@ -2770,7 +2835,12 @@ Das kann nicht rückgängig gemacht werden!</target> </trans-unit> <trans-unit id="History" xml:space="preserve"> <source>History</source> - <target>Vergangenheit</target> + <target>Nachrichtenverlauf</target> + <note>No comment provided by engineer.</note> + </trans-unit> + <trans-unit id="History is not sent to new members." xml:space="preserve"> + <source>History is not sent to new members.</source> + <target>Der Nachrichtenverlauf wird nicht an neue Gruppenmitglieder gesendet.</target> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="How SimpleX works" xml:space="preserve"> @@ -2808,11 +2878,6 @@ Das kann nicht rückgängig gemacht werden!</target> <target>Falls Sie sich nicht persönlich treffen können, zeigen Sie den QR-Code in einem Videoanruf oder teilen Sie den Link.</target> <note>No comment provided by engineer.</note> </trans-unit> - <trans-unit id="If you cannot meet in person, you can **scan QR code in the video call**, or your contact can share an invitation link." xml:space="preserve"> - <source>If you cannot meet in person, you can **scan QR code in the video call**, or your contact can share an invitation link.</source> - <target>Wenn Sie sich nicht persönlich treffen können, kann der **QR-Code während eines Videoanrufs gescannt werden**, oder Ihr Kontakt kann den Einladungslink über einen anderen Kanal mit Ihnen teilen.</target> - <note>No comment provided by engineer.</note> - </trans-unit> <trans-unit id="If you enter this passcode when opening the app, all app data will be irreversibly removed!" xml:space="preserve"> <source>If you enter this passcode when opening the app, all app data will be irreversibly removed!</source> <target>Wenn Sie diesen Zugangscode während des Öffnens der App eingeben, werden alle App-Daten unwiederbringlich gelöscht!</target> @@ -2868,6 +2933,11 @@ Das kann nicht rückgängig gemacht werden!</target> <target>Datenbank importieren</target> <note>No comment provided by engineer.</note> </trans-unit> + <trans-unit id="Improved message delivery" xml:space="preserve"> + <source>Improved message delivery</source> + <target>Verbesserte Zustellung von Nachrichten</target> + <note>No comment provided by engineer.</note> + </trans-unit> <trans-unit id="Improved privacy and security" xml:space="preserve"> <source>Improved privacy and security</source> <target>Verbesserte Privatsphäre und Sicherheit</target> @@ -2970,16 +3040,36 @@ Das kann nicht rückgängig gemacht werden!</target> <target>Schnittstelle</target> <note>No comment provided by engineer.</note> </trans-unit> + <trans-unit id="Invalid QR code" xml:space="preserve"> + <source>Invalid QR code</source> + <target>Ungültiger QR-Code</target> + <note>No comment provided by engineer.</note> + </trans-unit> <trans-unit id="Invalid connection link" xml:space="preserve"> <source>Invalid connection link</source> <target>Ungültiger Verbindungslink</target> <note>No comment provided by engineer.</note> </trans-unit> + <trans-unit id="Invalid display name!" xml:space="preserve"> + <source>Invalid display name!</source> + <target>Ungültiger Anzeigename!</target> + <note>No comment provided by engineer.</note> + </trans-unit> + <trans-unit id="Invalid link" xml:space="preserve"> + <source>Invalid link</source> + <target>Ungültiger Link</target> + <note>No comment provided by engineer.</note> + </trans-unit> <trans-unit id="Invalid name!" xml:space="preserve"> <source>Invalid name!</source> <target>Ungültiger Name!</target> <note>No comment provided by engineer.</note> </trans-unit> + <trans-unit id="Invalid response" xml:space="preserve"> + <source>Invalid response</source> + <target>Ungültige Reaktion</target> + <note>No comment provided by engineer.</note> + </trans-unit> <trans-unit id="Invalid server address!" xml:space="preserve"> <source>Invalid server address!</source> <target>Ungültige Serveradresse!</target> @@ -3071,6 +3161,11 @@ Das kann nicht rückgängig gemacht werden!</target> <target>Treten Sie der Gruppe bei</target> <note>No comment provided by engineer.</note> </trans-unit> + <trans-unit id="Join group conversations" xml:space="preserve"> + <source>Join group conversations</source> + <target>Gruppenunterhaltungen beitreten</target> + <note>No comment provided by engineer.</note> + </trans-unit> <trans-unit id="Join group?" xml:space="preserve"> <source>Join group?</source> <target>Der Gruppe beitreten?</target> @@ -3098,11 +3193,21 @@ Das ist Ihr Link für die Gruppe %@!</target> <target>Der Gruppe beitreten</target> <note>No comment provided by engineer.</note> </trans-unit> + <trans-unit id="Keep" xml:space="preserve"> + <source>Keep</source> + <target>Behalten</target> + <note>No comment provided by engineer.</note> + </trans-unit> <trans-unit id="Keep the app open to use it from desktop" xml:space="preserve"> <source>Keep the app open to use it from desktop</source> <target>Die App muss geöffnet bleiben, um sie vom Desktop aus nutzen zu können</target> <note>No comment provided by engineer.</note> </trans-unit> + <trans-unit id="Keep unused invitation?" xml:space="preserve"> + <source>Keep unused invitation?</source> + <target>Nicht genutzte Einladung behalten?</target> + <note>No comment provided by engineer.</note> + </trans-unit> <trans-unit id="Keep your connections" xml:space="preserve"> <source>Keep your connections</source> <target>Ihre Verbindungen beibehalten</target> @@ -3188,6 +3293,11 @@ Das ist Ihr Link für die Gruppe %@!</target> <target>Live Nachrichten</target> <note>No comment provided by engineer.</note> </trans-unit> + <trans-unit id="Local" xml:space="preserve"> + <source>Local</source> + <target>Lokal</target> + <note>No comment provided by engineer.</note> + </trans-unit> <trans-unit id="Local name" xml:space="preserve"> <source>Local name</source> <target>Lokaler Name</target> @@ -3230,7 +3340,7 @@ Das ist Ihr Link für die Gruppe %@!</target> </trans-unit> <trans-unit id="Make sure WebRTC ICE server addresses are in correct format, line separated and are not duplicated." xml:space="preserve"> <source>Make sure WebRTC ICE server addresses are in correct format, line separated and are not duplicated.</source> - <target>Stellen Sie sicher, dass die WebRTC ICE-Server Adressen das richtige Format haben, zeilenweise angeordnet und nicht doppelt vorhanden sind.</target> + <target>Stellen Sie sicher, dass die WebRTC ICE-Server Adressen das richtige Format haben, zeilenweise getrennt und nicht doppelt vorhanden sind.</target> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="Many people asked: *if SimpleX has no user identifiers, how can it deliver messages?*" xml:space="preserve"> @@ -3428,6 +3538,11 @@ Das ist Ihr Link für die Gruppe %@!</target> <target>Neuer Zugangscode</target> <note>No comment provided by engineer.</note> </trans-unit> + <trans-unit id="New chat" xml:space="preserve"> + <source>New chat</source> + <target>Neuer Chat</target> + <note>No comment provided by engineer.</note> + </trans-unit> <trans-unit id="New contact request" xml:space="preserve"> <source>New contact request</source> <target>Neue Kontaktanfrage</target> @@ -3515,7 +3630,7 @@ Das ist Ihr Link für die Gruppe %@!</target> </trans-unit> <trans-unit id="No history" xml:space="preserve"> <source>No history</source> - <target>Keine Vergangenheit</target> + <target>Kein Nachrichtenverlauf</target> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="No permission to record voice message" xml:space="preserve"> @@ -3552,16 +3667,16 @@ Das ist Ihr Link für die Gruppe %@!</target> - Gruppenmitglieder deaktivieren ("Beobachter"-Rolle)</target> <note>No comment provided by engineer.</note> </trans-unit> + <trans-unit id="OK" xml:space="preserve"> + <source>OK</source> + <target>OK</target> + <note>No comment provided by engineer.</note> + </trans-unit> <trans-unit id="Off" xml:space="preserve"> <source>Off</source> <target>Aus</target> <note>No comment provided by engineer.</note> </trans-unit> - <trans-unit id="Off (Local)" xml:space="preserve"> - <source>Off (Local)</source> - <target>Aus (Lokal)</target> - <note>No comment provided by engineer.</note> - </trans-unit> <trans-unit id="Ok" xml:space="preserve"> <source>Ok</source> <target>Ok</target> @@ -3622,9 +3737,9 @@ Das ist Ihr Link für die Gruppe %@!</target> <target>Nur Sie können Reaktionen auf Nachrichten geben.</target> <note>No comment provided by engineer.</note> </trans-unit> - <trans-unit id="Only you can irreversibly delete messages (your contact can mark them for deletion)." xml:space="preserve"> - <source>Only you can irreversibly delete messages (your contact can mark them for deletion).</source> - <target>Nur Sie können Nachrichten unwiederbringlich löschen (Ihr Kontakt kann sie zum Löschen markieren).</target> + <trans-unit id="Only you can irreversibly delete messages (your contact can mark them for deletion). (24 hours)" xml:space="preserve"> + <source>Only you can irreversibly delete messages (your contact can mark them for deletion). (24 hours)</source> + <target>Nur Sie können Nachrichten unwiederbringlich löschen (Ihr Kontakt kann sie zum Löschen markieren). (24 Stunden)</target> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="Only you can make calls." xml:space="preserve"> @@ -3647,9 +3762,9 @@ Das ist Ihr Link für die Gruppe %@!</target> <target>Nur Ihr Kontakt kann Reaktionen auf Nachrichten geben.</target> <note>No comment provided by engineer.</note> </trans-unit> - <trans-unit id="Only your contact can irreversibly delete messages (you can mark them for deletion)." xml:space="preserve"> - <source>Only your contact can irreversibly delete messages (you can mark them for deletion).</source> - <target>Nur Ihr Kontakt kann Nachrichten unwiederbringlich löschen (Sie können sie zum Löschen markieren).</target> + <trans-unit id="Only your contact can irreversibly delete messages (you can mark them for deletion). (24 hours)" xml:space="preserve"> + <source>Only your contact can irreversibly delete messages (you can mark them for deletion). (24 hours)</source> + <target>Nur Ihr Kontakt kann Nachrichten unwiederbringlich löschen (Sie können sie zum Löschen markieren). (24 Stunden)</target> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="Only your contact can make calls." xml:space="preserve"> @@ -3702,9 +3817,19 @@ Das ist Ihr Link für die Gruppe %@!</target> <target>Open-Source-Protokoll und -Code – Jede Person kann ihre eigenen Server aufsetzen und nutzen.</target> <note>No comment provided by engineer.</note> </trans-unit> - <trans-unit id="Opening database…" xml:space="preserve"> - <source>Opening database…</source> - <target>Öffne Datenbank …</target> + <trans-unit id="Opening app…" xml:space="preserve"> + <source>Opening app…</source> + <target>App wird geöffnet…</target> + <note>No comment provided by engineer.</note> + </trans-unit> + <trans-unit id="Or scan QR code" xml:space="preserve"> + <source>Or scan QR code</source> + <target>Oder den QR-Code scannen</target> + <note>No comment provided by engineer.</note> + </trans-unit> + <trans-unit id="Or show this code" xml:space="preserve"> + <source>Or show this code</source> + <target>Oder diesen QR-Code anzeigen</target> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="PING count" xml:space="preserve"> @@ -3747,10 +3872,10 @@ Das ist Ihr Link für die Gruppe %@!</target> <target>Passwort anzeigen</target> <note>No comment provided by engineer.</note> </trans-unit> - <trans-unit id="Paste" xml:space="preserve"> - <source>Paste</source> - <target>Einfügen</target> - <note>No comment provided by engineer.</note> + <trans-unit id="Past member %@" xml:space="preserve"> + <source>Past member %@</source> + <target>Ehemaliges Mitglied %@</target> + <note>past/unknown group member</note> </trans-unit> <trans-unit id="Paste desktop address" xml:space="preserve"> <source>Paste desktop address</source> @@ -3762,15 +3887,15 @@ Das ist Ihr Link für die Gruppe %@!</target> <target>Bild einfügen</target> <note>No comment provided by engineer.</note> </trans-unit> - <trans-unit id="Paste received link" xml:space="preserve"> - <source>Paste received link</source> - <target>Fügen Sie den erhaltenen Link ein</target> + <trans-unit id="Paste link to connect!" xml:space="preserve"> + <source>Paste link to connect!</source> + <target>Zum Verbinden den Link einfügen!</target> <note>No comment provided by engineer.</note> </trans-unit> - <trans-unit id="Paste the link you received to connect with your contact." xml:space="preserve"> - <source>Paste the link you received to connect with your contact.</source> - <target>Um sich mit Ihrem Kontakt zu verbinden, fügen Sie den erhaltenen Link in das Feld unten ein.</target> - <note>placeholder</note> + <trans-unit id="Paste the link you received" xml:space="preserve"> + <source>Paste the link you received</source> + <target>Fügen Sie den erhaltenen Link ein</target> + <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="People can connect to you only via the links you share." xml:space="preserve"> <source>People can connect to you only via the links you share.</source> @@ -3807,6 +3932,13 @@ Das ist Ihr Link für die Gruppe %@!</target> <target>Bitte überprüfen sie sowohl Ihre, als auch die Präferenzen Ihres Kontakts.</target> <note>No comment provided by engineer.</note> </trans-unit> + <trans-unit id="Please contact developers. Error: %@" xml:space="preserve"> + <source>Please contact developers. +Error: %@</source> + <target>Bitte nehmen Sie Kontakt mit den Entwicklern auf. +Fehler: %@</target> + <note>No comment provided by engineer.</note> + </trans-unit> <trans-unit id="Please contact group admin." xml:space="preserve"> <source>Please contact group admin.</source> <target>Bitte kontaktieren Sie den Gruppen-Administrator.</target> @@ -3892,6 +4024,11 @@ Das ist Ihr Link für die Gruppe %@!</target> <target>Neutrale Dateinamen</target> <note>No comment provided by engineer.</note> </trans-unit> + <trans-unit id="Private notes" xml:space="preserve"> + <source>Private notes</source> + <target>Private Notizen</target> + <note>name of notes to self</note> + </trans-unit> <trans-unit id="Profile and server connections" xml:space="preserve"> <source>Profile and server connections</source> <target>Profil und Serververbindungen</target> @@ -4012,6 +4149,11 @@ Das ist Ihr Link für die Gruppe %@!</target> <target>Mehr dazu in der [Benutzeranleitung](https://simplex.chat/docs/guide/app-settings.html#your-simplex-contact-address) lesen.</target> <note>No comment provided by engineer.</note> </trans-unit> + <trans-unit id="Read more in [User Guide](https://simplex.chat/docs/guide/chat-profiles.html#incognito-mode)." xml:space="preserve"> + <source>Read more in [User Guide](https://simplex.chat/docs/guide/chat-profiles.html#incognito-mode).</source> + <target>Lesen Sie mehr dazu im [Benutzerhandbuch](https://simplex.chat/docs/guide/chat-profiles.html#incognito-mode).</target> + <note>No comment provided by engineer.</note> + </trans-unit> <trans-unit id="Read more in [User Guide](https://simplex.chat/docs/guide/readme.html#connect-to-friends)." xml:space="preserve"> <source>Read more in [User Guide](https://simplex.chat/docs/guide/readme.html#connect-to-friends).</source> <target>Mehr dazu in der [Benutzeranleitung](https://simplex.chat/docs/guide/readme.html#connect-to-friends) lesen.</target> @@ -4067,6 +4209,11 @@ Das ist Ihr Link für die Gruppe %@!</target> <target>Empfangen über</target> <note>No comment provided by engineer.</note> </trans-unit> + <trans-unit id="Recent history and improved [directory bot](simplex:/contact#/?v=1-4&smp=smp%3A%2F%2Fu2dS9sG8nMNURyZwqASV4yROM28Er0luVTx5X1CsMrU%3D%40smp4.simplex.im%2FeXSPwqTkKyDO3px4fLf1wx3MvPdjdLW3%23%2F%3Fv%3D1-2%26dh%3DMCowBQYDK2VuAyEAaiv6MkMH44L2TcYrt_CsX3ZvM11WgbMEUn0hkIKTOho%253D%26srv%3Do5vmywmrnaxalvz6wi3zicyftgio6psuvyniis6gco6bp6ekl4cqj4id.onion)." xml:space="preserve"> + <source>Recent history and improved [directory bot](simplex:/contact#/?v=1-4&smp=smp%3A%2F%2Fu2dS9sG8nMNURyZwqASV4yROM28Er0luVTx5X1CsMrU%3D%40smp4.simplex.im%2FeXSPwqTkKyDO3px4fLf1wx3MvPdjdLW3%23%2F%3Fv%3D1-2%26dh%3DMCowBQYDK2VuAyEAaiv6MkMH44L2TcYrt_CsX3ZvM11WgbMEUn0hkIKTOho%253D%26srv%3Do5vmywmrnaxalvz6wi3zicyftgio6psuvyniis6gco6bp6ekl4cqj4id.onion).</source> + <target>Aktueller Nachrichtenverlauf und verbesserter [Gruppenverzeichnis-Bot](simplex:/contact#/?v=1-4&smp=smp%3A%2F%2Fu2dS9sG8nMNURyZwqASV4yROM28Er0luVTx5X1CsMrU%3D%40smp4.simplex.im%2FeXSPwqTkKyDO3px4fLf1wx3MvPdjdLW3%23%2F%3Fv%3D1-2%26dh%3DMCowBQYDK2VuAyEAaiv6MkMH44L2TcYrt_CsX3ZvM11WgbMEUn0hkIKTOho%253D%26srv%3Do5vmywmrnaxalvz6wi3zicyftgio6psuvyniis6gco6bp6ekl4cqj4id.onion).</target> + <note>No comment provided by engineer.</note> + </trans-unit> <trans-unit id="Recipients see updates as you type them." xml:space="preserve"> <source>Recipients see updates as you type them.</source> <target>Die Empfänger sehen Nachrichtenaktualisierungen, während Sie sie eingeben.</target> @@ -4222,6 +4369,11 @@ Das ist Ihr Link für die Gruppe %@!</target> <target>Fehler bei der Wiederherstellung der Datenbank</target> <note>No comment provided by engineer.</note> </trans-unit> + <trans-unit id="Retry" xml:space="preserve"> + <source>Retry</source> + <target>Wiederholen</target> + <note>No comment provided by engineer.</note> + </trans-unit> <trans-unit id="Reveal" xml:space="preserve"> <source>Reveal</source> <target>Aufdecken</target> @@ -4347,6 +4499,11 @@ Das ist Ihr Link für die Gruppe %@!</target> <target>Gespeicherte WebRTC ICE-Server werden entfernt</target> <note>No comment provided by engineer.</note> </trans-unit> + <trans-unit id="Saved message" xml:space="preserve"> + <source>Saved message</source> + <target>Gespeicherte Nachricht</target> + <note>message info title</note> + </trans-unit> <trans-unit id="Scan QR code" xml:space="preserve"> <source>Scan QR code</source> <target>QR-Code scannen</target> @@ -4377,6 +4534,16 @@ Das ist Ihr Link für die Gruppe %@!</target> <target>Suche</target> <note>No comment provided by engineer.</note> </trans-unit> + <trans-unit id="Search bar accepts invitation links." xml:space="preserve"> + <source>Search bar accepts invitation links.</source> + <target>Von der Suchleiste werden Einladungslinks akzeptiert.</target> + <note>No comment provided by engineer.</note> + </trans-unit> + <trans-unit id="Search or paste SimpleX link" xml:space="preserve"> + <source>Search or paste SimpleX link</source> + <target>Suchen oder fügen Sie den SimpleX-Link ein</target> + <note>No comment provided by engineer.</note> + </trans-unit> <trans-unit id="Secure queue" xml:space="preserve"> <source>Secure queue</source> <target>Sichere Warteschlange</target> @@ -4482,6 +4649,11 @@ Das ist Ihr Link für die Gruppe %@!</target> <target>Senden Sie diese aus dem Fotoalbum oder von individuellen Tastaturen.</target> <note>No comment provided by engineer.</note> </trans-unit> + <trans-unit id="Send up to 100 last messages to new members." xml:space="preserve"> + <source>Send up to 100 last messages to new members.</source> + <target>Bis zu 100 der letzten Nachrichten an neue Gruppenmitglieder senden.</target> + <note>No comment provided by engineer.</note> + </trans-unit> <trans-unit id="Sender cancelled file transfer." xml:space="preserve"> <source>Sender cancelled file transfer.</source> <target>Der Absender hat die Dateiübertragung abgebrochen.</target> @@ -4652,9 +4824,9 @@ Das ist Ihr Link für die Gruppe %@!</target> <target>Link teilen</target> <note>No comment provided by engineer.</note> </trans-unit> - <trans-unit id="Share one-time invitation link" xml:space="preserve"> - <source>Share one-time invitation link</source> - <target>Einmal-Einladungslink teilen</target> + <trans-unit id="Share this 1-time invite link" xml:space="preserve"> + <source>Share this 1-time invite link</source> + <target>Teilen Sie diesen Einmal-Einladungslink</target> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="Share with contacts" xml:space="preserve"> @@ -4777,16 +4949,16 @@ Das ist Ihr Link für die Gruppe %@!</target> <target>Jemand</target> <note>notification title</note> </trans-unit> - <trans-unit id="Start a new chat" xml:space="preserve"> - <source>Start a new chat</source> - <target>Starten Sie einen neuen Chat</target> - <note>No comment provided by engineer.</note> - </trans-unit> <trans-unit id="Start chat" xml:space="preserve"> <source>Start chat</source> <target>Starten Sie den Chat</target> <note>No comment provided by engineer.</note> </trans-unit> + <trans-unit id="Start chat?" xml:space="preserve"> + <source>Start chat?</source> + <target>Chat starten?</target> + <note>No comment provided by engineer.</note> + </trans-unit> <trans-unit id="Start migration" xml:space="preserve"> <source>Start migration</source> <target>Starten Sie die Migration</target> @@ -4894,12 +5066,12 @@ Das ist Ihr Link für die Gruppe %@!</target> </trans-unit> <trans-unit id="Tap to Connect" xml:space="preserve"> <source>Tap to Connect</source> - <target>Zum Verbinden antippen</target> + <target>Zum Verbinden tippen</target> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="Tap to activate profile." xml:space="preserve"> <source>Tap to activate profile.</source> - <target>Tippen Sie auf das Profil um es zu aktivieren.</target> + <target>Zum Aktivieren des Profils tippen.</target> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="Tap to join" xml:space="preserve"> @@ -4909,12 +5081,22 @@ Das ist Ihr Link für die Gruppe %@!</target> </trans-unit> <trans-unit id="Tap to join incognito" xml:space="preserve"> <source>Tap to join incognito</source> - <target>Tippen, um Inkognito beizutreten</target> + <target>Zum Inkognito beitreten tippen</target> + <note>No comment provided by engineer.</note> + </trans-unit> + <trans-unit id="Tap to paste link" xml:space="preserve"> + <source>Tap to paste link</source> + <target>Zum Link einfügen tippen</target> + <note>No comment provided by engineer.</note> + </trans-unit> + <trans-unit id="Tap to scan" xml:space="preserve"> + <source>Tap to scan</source> + <target>Zum Scannen tippen</target> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="Tap to start a new chat" xml:space="preserve"> <source>Tap to start a new chat</source> - <target>Tippen, um einen neuen Chat zu starten</target> + <target>Zum Starten eines neuen Chats tippen</target> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="Test failed at step %@." xml:space="preserve"> @@ -4974,6 +5156,11 @@ Dies kann passieren, wenn es einen Fehler gegeben hat oder die Verbindung kompro <target>Die Änderung des Datenbank-Passworts konnte nicht abgeschlossen werden.</target> <note>No comment provided by engineer.</note> </trans-unit> + <trans-unit id="The code you scanned is not a SimpleX link QR code." xml:space="preserve"> + <source>The code you scanned is not a SimpleX link QR code.</source> + <target>Der von Ihnen gescannte Code ist kein SimpleX-Link-QR-Code.</target> + <note>No comment provided by engineer.</note> + </trans-unit> <trans-unit id="The connection you accepted will be cancelled!" xml:space="preserve"> <source>The connection you accepted will be cancelled!</source> <target>Die von Ihnen akzeptierte Verbindung wird abgebrochen!</target> @@ -5036,7 +5223,12 @@ Dies kann passieren, wenn es einen Fehler gegeben hat oder die Verbindung kompro </trans-unit> <trans-unit id="The servers for new connections of your current chat profile **%@**." xml:space="preserve"> <source>The servers for new connections of your current chat profile **%@**.</source> - <target>Server der neuen Verbindungen von Ihrem aktuellen Chat-Profil **%@**.</target> + <target>Mögliche Server für neue Verbindungen von Ihrem aktuellen Chat-Profil **%@**.</target> + <note>No comment provided by engineer.</note> + </trans-unit> + <trans-unit id="The text you pasted is not a SimpleX link." xml:space="preserve"> + <source>The text you pasted is not a SimpleX link.</source> + <target>Der von Ihnen eingefügte Text ist kein SimpleX-Link.</target> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="Theme" xml:space="preserve"> @@ -5044,16 +5236,6 @@ Dies kann passieren, wenn es einen Fehler gegeben hat oder die Verbindung kompro <target>Design</target> <note>No comment provided by engineer.</note> </trans-unit> - <trans-unit id="There should be at least one user profile." xml:space="preserve"> - <source>There should be at least one user profile.</source> - <target>Es muss mindestens ein Benutzer-Profil vorhanden sein.</target> - <note>No comment provided by engineer.</note> - </trans-unit> - <trans-unit id="There should be at least one visible user profile." xml:space="preserve"> - <source>There should be at least one visible user profile.</source> - <target>Es muss mindestens ein sichtbares Benutzer-Profil vorhanden sein.</target> - <note>No comment provided by engineer.</note> - </trans-unit> <trans-unit id="These settings are for your current profile **%@**." xml:space="preserve"> <source>These settings are for your current profile **%@**.</source> <target>Diese Einstellungen betreffen Ihr aktuelles Profil **%@**.</target> @@ -5084,6 +5266,11 @@ Dies kann passieren, wenn es einen Fehler gegeben hat oder die Verbindung kompro <target>Dieser Gerätename</target> <note>No comment provided by engineer.</note> </trans-unit> + <trans-unit id="This display name is invalid. Please choose another name." xml:space="preserve"> + <source>This display name is invalid. Please choose another name.</source> + <target>Der Anzeigename ist ungültig. Bitte wählen Sie einen anderen Namen.</target> + <note>No comment provided by engineer.</note> + </trans-unit> <trans-unit id="This group has over %lld members, delivery receipts are not sent." xml:space="preserve"> <source>This group has over %lld members, delivery receipts are not sent.</source> <target>Es werden keine Empfangsbestätigungen gesendet, da diese Gruppe über %lld Mitglieder hat.</target> @@ -5186,16 +5373,16 @@ Sie werden aufgefordert, die Authentifizierung abzuschließen, bevor diese Funkt <target>Versuche die Verbindung mit dem Server aufzunehmen, der für den Empfang von Nachrichten mit diesem Kontakt genutzt wird.</target> <note>No comment provided by engineer.</note> </trans-unit> + <trans-unit id="Turkish interface" xml:space="preserve"> + <source>Turkish interface</source> + <target>Türkische Bedienoberfläche</target> + <note>No comment provided by engineer.</note> + </trans-unit> <trans-unit id="Turn off" xml:space="preserve"> <source>Turn off</source> <target>Abschalten</target> <note>No comment provided by engineer.</note> </trans-unit> - <trans-unit id="Turn off notifications?" xml:space="preserve"> - <source>Turn off notifications?</source> - <target>Benachrichtigungen abschalten?</target> - <note>No comment provided by engineer.</note> - </trans-unit> <trans-unit id="Turn on" xml:space="preserve"> <source>Turn on</source> <target>Einschalten</target> @@ -5211,11 +5398,21 @@ Sie werden aufgefordert, die Authentifizierung abzuschließen, bevor diese Funkt <target>Freigeben</target> <note>No comment provided by engineer.</note> </trans-unit> + <trans-unit id="Unblock for all" xml:space="preserve"> + <source>Unblock for all</source> + <target>Für Alle freigeben</target> + <note>No comment provided by engineer.</note> + </trans-unit> <trans-unit id="Unblock member" xml:space="preserve"> <source>Unblock member</source> <target>Mitglied freigeben</target> <note>No comment provided by engineer.</note> </trans-unit> + <trans-unit id="Unblock member for all?" xml:space="preserve"> + <source>Unblock member for all?</source> + <target>Mitglied für Alle freigeben?</target> + <note>No comment provided by engineer.</note> + </trans-unit> <trans-unit id="Unblock member?" xml:space="preserve"> <source>Unblock member?</source> <target>Mitglied freigeben?</target> @@ -5313,6 +5510,11 @@ Bitten Sie Ihren Kontakt darum einen weiteren Verbindungs-Link zu erzeugen, um s <target>Ungelesen</target> <note>No comment provided by engineer.</note> </trans-unit> + <trans-unit id="Up to 100 last messages are sent to new members." xml:space="preserve"> + <source>Up to 100 last messages are sent to new members.</source> + <target>Bis zu 100 der letzten Nachrichten werden an neue Mitglieder gesendet.</target> + <note>No comment provided by engineer.</note> + </trans-unit> <trans-unit id="Update" xml:space="preserve"> <source>Update</source> <target>Aktualisieren</target> @@ -5398,6 +5600,11 @@ Bitten Sie Ihren Kontakt darum einen weiteren Verbindungs-Link zu erzeugen, um s <target>Nutzen Sie das neue Inkognito-Profil</target> <note>No comment provided by engineer.</note> </trans-unit> + <trans-unit id="Use only local notifications?" xml:space="preserve"> + <source>Use only local notifications?</source> + <target>Nur lokale Benachrichtigungen nutzen?</target> + <note>No comment provided by engineer.</note> + </trans-unit> <trans-unit id="Use server" xml:space="preserve"> <source>Use server</source> <target>Server nutzen</target> @@ -5478,6 +5685,11 @@ Bitten Sie Ihren Kontakt darum einen weiteren Verbindungs-Link zu erzeugen, um s <target>Schauen Sie sich den Sicherheitscode an</target> <note>No comment provided by engineer.</note> </trans-unit> + <trans-unit id="Visible history" xml:space="preserve"> + <source>Visible history</source> + <target>Sichtbarer Nachrichtenverlauf</target> + <note>chat feature</note> + </trans-unit> <trans-unit id="Voice messages" xml:space="preserve"> <source>Voice messages</source> <target>Sprachnachrichten</target> @@ -5563,11 +5775,21 @@ Bitten Sie Ihren Kontakt darum einen weiteren Verbindungs-Link zu erzeugen, um s <target>Wenn Sie ein Inkognito-Profil mit Jemandem teilen, wird dieses Profil auch für die Gruppen verwendet, für die Sie von diesem Kontakt eingeladen werden.</target> <note>No comment provided by engineer.</note> </trans-unit> + <trans-unit id="With encrypted files and media." xml:space="preserve"> + <source>With encrypted files and media.</source> + <target>Mit verschlüsselten Dateien und Medien.</target> + <note>No comment provided by engineer.</note> + </trans-unit> <trans-unit id="With optional welcome message." xml:space="preserve"> <source>With optional welcome message.</source> <target>Mit optionaler Begrüßungsmeldung.</target> <note>No comment provided by engineer.</note> </trans-unit> + <trans-unit id="With reduced battery usage." xml:space="preserve"> + <source>With reduced battery usage.</source> + <target>Mit reduziertem Akkuverbrauch.</target> + <note>No comment provided by engineer.</note> + </trans-unit> <trans-unit id="Wrong database passphrase" xml:space="preserve"> <source>Wrong database passphrase</source> <target>Falsches Datenbank-Passwort</target> @@ -5585,7 +5807,7 @@ Bitten Sie Ihren Kontakt darum einen weiteren Verbindungs-Link zu erzeugen, um s </trans-unit> <trans-unit id="You" xml:space="preserve"> <source>You</source> - <target>Ihre Daten</target> + <target>Profil</target> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="You accepted connection" xml:space="preserve"> @@ -5660,11 +5882,6 @@ Verbindungsanfrage wiederholen?</target> <target>Sie können Anrufe ohne Geräte- und App-Authentifizierung vom Sperrbildschirm aus annehmen.</target> <note>No comment provided by engineer.</note> </trans-unit> - <trans-unit id="You can also connect by clicking the link. If it opens in the browser, click **Open in mobile app** button." xml:space="preserve"> - <source>You can also connect by clicking the link. If it opens in the browser, click **Open in mobile app** button.</source> - <target>Sie können sich auch verbinden, indem Sie auf den Link klicken. Wenn er im Browser geöffnet wird, klicken Sie auf die Schaltfläche **In mobiler App öffnen**.</target> - <note>No comment provided by engineer.</note> - </trans-unit> <trans-unit id="You can create it later" xml:space="preserve"> <source>You can create it later</source> <target>Sie können dies später erstellen</target> @@ -5685,6 +5902,11 @@ Verbindungsanfrage wiederholen?</target> <target>Sie können ein Benutzerprofil verbergen oder stummschalten - wischen Sie es nach rechts.</target> <note>No comment provided by engineer.</note> </trans-unit> + <trans-unit id="You can make it visible to your SimpleX contacts via Settings." xml:space="preserve"> + <source>You can make it visible to your SimpleX contacts via Settings.</source> + <target>Sie können sie über Einstellungen für Ihre SimpleX-Kontakte sichtbar machen.</target> + <note>No comment provided by engineer.</note> + </trans-unit> <trans-unit id="You can now send messages to %@" xml:space="preserve"> <source>You can now send messages to %@</source> <target>Sie können nun Nachrichten an %@ versenden</target> @@ -5725,6 +5947,11 @@ Verbindungsanfrage wiederholen?</target> <target>Um Nachrichteninhalte zu formatieren, können Sie Markdowns verwenden:</target> <note>No comment provided by engineer.</note> </trans-unit> + <trans-unit id="You can view invitation link again in connection details." xml:space="preserve"> + <source>You can view invitation link again in connection details.</source> + <target>Den Einladungslink können Sie in den Details der Verbindung nochmals sehen.</target> + <note>No comment provided by engineer.</note> + </trans-unit> <trans-unit id="You can't send messages!" xml:space="preserve"> <source>You can't send messages!</source> <target>Sie können keine Nachrichten versenden!</target> @@ -5834,12 +6061,12 @@ Verbindungsanfrage wiederholen?</target> </trans-unit> <trans-unit id="You will stop receiving messages from this group. Chat history will be preserved." xml:space="preserve"> <source>You will stop receiving messages from this group. Chat history will be preserved.</source> - <target>Sie werden von dieser Gruppe keine Nachrichten mehr erhalten. Der Chatverlauf wird beibehalten.</target> + <target>Sie werden von dieser Gruppe keine Nachrichten mehr erhalten. Der Nachrichtenverlauf wird beibehalten.</target> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="You won't lose your contacts if you later delete your address." xml:space="preserve"> <source>You won't lose your contacts if you later delete your address.</source> - <target>Sie werden Ihre mit dieser Adresse verbundenen Kontakte nicht verlieren, wenn Sie diese Adresse später löschen.</target> + <target>Sie werden Ihre damit verbundenen Kontakte nicht verlieren, wenn Sie diese Adresse später löschen.</target> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="You're trying to invite contact with whom you've shared an incognito profile to the group in which you're using your main profile" xml:space="preserve"> @@ -5914,13 +6141,6 @@ Sie können diese Verbindung abbrechen und den Kontakt entfernen (und es später <target>Ihre Kontakte können die unwiederbringliche Löschung von Nachrichten erlauben.</target> <note>No comment provided by engineer.</note> </trans-unit> - <trans-unit id="Your contacts in SimpleX will see it. You can change it in Settings." xml:space="preserve"> - <source>Your contacts in SimpleX will see it. -You can change it in Settings.</source> - <target>Ihre Kontakte in SimpleX werden es sehen. -Sie können es in den Einstellungen ändern.</target> - <note>No comment provided by engineer.</note> - </trans-unit> <trans-unit id="Your contacts will remain connected." xml:space="preserve"> <source>Your contacts will remain connected.</source> <target>Ihre Kontakte bleiben verbunden.</target> @@ -5985,7 +6205,7 @@ SimpleX-Server können Ihr Profil nicht einsehen.</target> </trans-unit> <trans-unit id="Your settings" xml:space="preserve"> <source>Your settings</source> - <target>Ihre Einstellungen</target> + <target>Einstellungen</target> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="[Contribute](https://github.com/simplex-chat/simplex-chat#contribute)" xml:space="preserve"> @@ -6070,9 +6290,19 @@ SimpleX-Server können Ihr Profil nicht einsehen.</target> </trans-unit> <trans-unit id="blocked" xml:space="preserve"> <source>blocked</source> - <target>blockiert</target> + <target>Blockiert</target> <note>No comment provided by engineer.</note> </trans-unit> + <trans-unit id="blocked %@" xml:space="preserve"> + <source>blocked %@</source> + <target>%@ wurde blockiert</target> + <note>rcv group event chat item</note> + </trans-unit> + <trans-unit id="blocked by admin" xml:space="preserve"> + <source>blocked by admin</source> + <target>wurde vom Administrator blockiert</target> + <note>blocked chat item</note> + </trans-unit> <trans-unit id="bold" xml:space="preserve"> <source>bold</source> <target>fett</target> @@ -6100,7 +6330,7 @@ SimpleX-Server können Ihr Profil nicht einsehen.</target> </trans-unit> <trans-unit id="changed address for you" xml:space="preserve"> <source>changed address for you</source> - <target>wechselte die Adresse für Sie</target> + <target>Wechselte die Empfängeradresse von Ihnen</target> <note>chat item text</note> </trans-unit> <trans-unit id="changed role of %@ to %@" xml:space="preserve"> @@ -6115,12 +6345,12 @@ SimpleX-Server können Ihr Profil nicht einsehen.</target> </trans-unit> <trans-unit id="changing address for %@…" xml:space="preserve"> <source>changing address for %@…</source> - <target>Adresse von %@ wechseln…</target> + <target>Empfängeradresse für %@ wechseln wird gestartet…</target> <note>chat item text</note> </trans-unit> <trans-unit id="changing address…" xml:space="preserve"> <source>changing address…</source> - <target>Wechsel der Adresse…</target> + <target>Wechsel der Empfängeradresse wurde gestartet…</target> <note>chat item text</note> </trans-unit> <trans-unit id="colored" xml:space="preserve"> @@ -6193,6 +6423,11 @@ SimpleX-Server können Ihr Profil nicht einsehen.</target> <target>Verbindung:%@</target> <note>connection information</note> </trans-unit> + <trans-unit id="contact %@ changed to %@" xml:space="preserve"> + <source>contact %1$@ changed to %2$@</source> + <target>Der Kontaktname %1$@ wurde auf %2$@ geändert</target> + <note>profile update event chat item</note> + </trans-unit> <trans-unit id="contact has e2e encryption" xml:space="preserve"> <source>contact has e2e encryption</source> <target>Kontakt nutzt E2E-Verschlüsselung</target> @@ -6463,6 +6698,11 @@ SimpleX-Server können Ihr Profil nicht einsehen.</target> <target>Mitglied</target> <note>member role</note> </trans-unit> + <trans-unit id="member %@ changed to %@" xml:space="preserve"> + <source>member %1$@ changed to %2$@</source> + <target>Der Mitgliedsname %1$@ wurde auf %2$@ geändert</target> + <note>profile update event chat item</note> + </trans-unit> <trans-unit id="member connected" xml:space="preserve"> <source>connected</source> <target>ist der Gruppe beigetreten</target> @@ -6585,6 +6825,16 @@ SimpleX-Server können Ihr Profil nicht einsehen.</target> <target>hat %@ aus der Gruppe entfernt</target> <note>rcv group event chat item</note> </trans-unit> + <trans-unit id="removed contact address" xml:space="preserve"> + <source>removed contact address</source> + <target>Kontaktadresse wurde entfernt</target> + <note>profile update event chat item</note> + </trans-unit> + <trans-unit id="removed profile picture" xml:space="preserve"> + <source>removed profile picture</source> + <target>Profil-Bild wurde entfernt</target> + <note>profile update event chat item</note> + </trans-unit> <trans-unit id="removed you" xml:space="preserve"> <source>removed you</source> <target>hat Sie aus der Gruppe entfernt</target> @@ -6615,6 +6865,16 @@ SimpleX-Server können Ihr Profil nicht einsehen.</target> <target>Direktnachricht senden</target> <note>No comment provided by engineer.</note> </trans-unit> + <trans-unit id="set new contact address" xml:space="preserve"> + <source>set new contact address</source> + <target>Neue Kontaktadresse wurde festgelegt</target> + <note>profile update event chat item</note> + </trans-unit> + <trans-unit id="set new profile picture" xml:space="preserve"> + <source>set new profile picture</source> + <target>Neues Profil-Bild wurde festgelegt</target> + <note>profile update event chat item</note> + </trans-unit> <trans-unit id="starting…" xml:space="preserve"> <source>starting…</source> <target>Verbindung wird gestartet…</target> @@ -6630,16 +6890,31 @@ SimpleX-Server können Ihr Profil nicht einsehen.</target> <target>Dieser Kontakt</target> <note>notification title</note> </trans-unit> + <trans-unit id="unblocked %@" xml:space="preserve"> + <source>unblocked %@</source> + <target>%@ wurde freigegeben</target> + <note>rcv group event chat item</note> + </trans-unit> <trans-unit id="unknown" xml:space="preserve"> <source>unknown</source> <target>Unbekannt</target> <note>connection info</note> </trans-unit> + <trans-unit id="unknown status" xml:space="preserve"> + <source>unknown status</source> + <target>unbekannter Gruppenmitglieds-Status</target> + <note>No comment provided by engineer.</note> + </trans-unit> <trans-unit id="updated group profile" xml:space="preserve"> <source>updated group profile</source> <target>Aktualisiertes Gruppenprofil</target> <note>rcv group event chat item</note> </trans-unit> + <trans-unit id="updated profile" xml:space="preserve"> + <source>updated profile</source> + <target>Das Profil wurde aktualisiert</target> + <note>profile update event chat item</note> + </trans-unit> <trans-unit id="v%@" xml:space="preserve"> <source>v%@</source> <target>v%@</target> @@ -6710,14 +6985,19 @@ SimpleX-Server können Ihr Profil nicht einsehen.</target> <target>Sie sind Beobachter</target> <note>No comment provided by engineer.</note> </trans-unit> + <trans-unit id="you blocked %@" xml:space="preserve"> + <source>you blocked %@</source> + <target>Sie haben %@ blockiert</target> + <note>snd group event chat item</note> + </trans-unit> <trans-unit id="you changed address" xml:space="preserve"> <source>you changed address</source> - <target>Sie haben die Adresse gewechselt</target> + <target>Die Empfängeradresse wurde gewechselt</target> <note>chat item text</note> </trans-unit> <trans-unit id="you changed address for %@" xml:space="preserve"> <source>you changed address for %@</source> - <target>Sie haben die Adresse für %@ gewechselt</target> + <target>Die Empfängeradresse für %@ wurde gewechselt</target> <note>chat item text</note> </trans-unit> <trans-unit id="you changed role for yourself to %@" xml:space="preserve"> @@ -6750,6 +7030,11 @@ SimpleX-Server können Ihr Profil nicht einsehen.</target> <target>Sie haben Inkognito einen Einmal-Link geteilt</target> <note>chat list item description</note> </trans-unit> + <trans-unit id="you unblocked %@" xml:space="preserve"> + <source>you unblocked %@</source> + <target>Sie haben %@ freigegeben</target> + <note>snd group event chat item</note> + </trans-unit> <trans-unit id="you: " xml:space="preserve"> <source>you: </source> <target>Sie: </target> diff --git a/apps/ios/SimpleX Localizations/el.xcloc/Localized Contents/el.xliff b/apps/ios/SimpleX Localizations/el.xcloc/Localized Contents/el.xliff index 7649b595cd..18051ae350 100644 --- a/apps/ios/SimpleX Localizations/el.xcloc/Localized Contents/el.xliff +++ b/apps/ios/SimpleX Localizations/el.xcloc/Localized Contents/el.xliff @@ -31,48 +31,59 @@ Available in v5.1</source> <source> (</source> <note>No comment provided by engineer.</note> </trans-unit> - <trans-unit id=" (can be copied)" xml:space="preserve"> + <trans-unit id=" (can be copied)" xml:space="preserve" approved="no"> <source> (can be copied)</source> + <target state="translated"> (μπορεί να αντιγραφή)</target> <note>No comment provided by engineer.</note> </trans-unit> - <trans-unit id="!1 colored!" xml:space="preserve"> + <trans-unit id="!1 colored!" xml:space="preserve" approved="no"> <source>!1 colored!</source> + <target state="translated">!1 έγχρωμο!</target> <note>No comment provided by engineer.</note> </trans-unit> - <trans-unit id="#secret#" xml:space="preserve"> + <trans-unit id="#secret#" xml:space="preserve" approved="no"> <source>#secret#</source> + <target state="translated">#μυστικό#</target> <note>No comment provided by engineer.</note> </trans-unit> - <trans-unit id="%@" xml:space="preserve"> + <trans-unit id="%@" xml:space="preserve" approved="no"> <source>%@</source> + <target state="translated">%@</target> <note>No comment provided by engineer.</note> </trans-unit> - <trans-unit id="%@ %@" xml:space="preserve"> + <trans-unit id="%@ %@" xml:space="preserve" approved="no"> <source>%@ %@</source> + <target state="translated">%@ %@</target> <note>No comment provided by engineer.</note> </trans-unit> - <trans-unit id="%@ / %@" xml:space="preserve"> + <trans-unit id="%@ / %@" xml:space="preserve" approved="no"> <source>%@ / %@</source> + <target state="translated">%@ / %@</target> <note>No comment provided by engineer.</note> </trans-unit> - <trans-unit id="%@ is connected!" xml:space="preserve"> + <trans-unit id="%@ is connected!" xml:space="preserve" approved="no"> <source>%@ is connected!</source> + <target state="translated">%@ είναι συνδεδεμένο!</target> <note>notification title</note> </trans-unit> - <trans-unit id="%@ is not verified" xml:space="preserve"> + <trans-unit id="%@ is not verified" xml:space="preserve" approved="no"> <source>%@ is not verified</source> + <target state="translated">%@ δεν είναι επαληθευμένο</target> <note>No comment provided by engineer.</note> </trans-unit> - <trans-unit id="%@ is verified" xml:space="preserve"> + <trans-unit id="%@ is verified" xml:space="preserve" approved="no"> <source>%@ is verified</source> + <target state="translated">%@ είναι επαληθευμένο</target> <note>No comment provided by engineer.</note> </trans-unit> - <trans-unit id="%@ servers" xml:space="preserve"> + <trans-unit id="%@ servers" xml:space="preserve" approved="no"> <source>%@ servers</source> + <target state="translated">%@ διακομιστές</target> <note>No comment provided by engineer.</note> </trans-unit> - <trans-unit id="%@ wants to connect!" xml:space="preserve"> + <trans-unit id="%@ wants to connect!" xml:space="preserve" approved="no"> <source>%@ wants to connect!</source> + <target state="translated">%@ θέλει να συνδεθεί!</target> <note>notification title</note> </trans-unit> <trans-unit id="%d days" xml:space="preserve"> @@ -4162,6 +4173,66 @@ SimpleX servers cannot see your profile.</source> <source>\~strike~</source> <note>No comment provided by engineer.</note> </trans-unit> + <trans-unit id="%@ connected" xml:space="preserve" approved="no"> + <source>%@ connected</source> + <target state="translated">%@ συνδεδεμένο</target> + <note>No comment provided by engineer.</note> + </trans-unit> + <trans-unit id="# %@" xml:space="preserve" approved="no"> + <source># %@</source> + <target state="translated"># %@</target> + <note>copied message info title, # <title></note> + </trans-unit> + <trans-unit id="%@ and %@" xml:space="preserve" approved="no"> + <source>%@ and %@</source> + <target state="translated">%@ και %@</target> + <note>No comment provided by engineer.</note> + </trans-unit> + <trans-unit id="%@ at %@:" xml:space="preserve" approved="no"> + <source>%1$@ at %2$@:</source> + <target state="translated">%1$@ στις %2$@:</target> + <note>copied message info, <sender> at <time></note> + </trans-unit> + <trans-unit id="## History" xml:space="preserve" approved="no"> + <source>## History</source> + <target state="translated">## Ιστορικό</target> + <note>copied message info</note> + </trans-unit> + <trans-unit id="## In reply to" xml:space="preserve" approved="no"> + <source>## In reply to</source> + <target state="translated">## Ως απαντηση σε</target> + <note>copied message info</note> + </trans-unit> + <trans-unit id="%@ (current)" xml:space="preserve" approved="no"> + <source>%@ (current)</source> + <target state="translated">%@ (τωρινό)</target> + <note>No comment provided by engineer.</note> + </trans-unit> + <trans-unit id="%@ (current):" xml:space="preserve" approved="no"> + <source>%@ (current):</source> + <target state="translated">%@ (τωρινό):</target> + <note>copied message info</note> + </trans-unit> + <trans-unit id="%@ and %@ connected" xml:space="preserve" approved="no"> + <source>%@ and %@ connected</source> + <target state="translated">%@ και %@ συνδεδεμένο</target> + <note>No comment provided by engineer.</note> + </trans-unit> + <trans-unit id="%@:" xml:space="preserve" approved="no"> + <source>%@:</source> + <target state="translated">%@:</target> + <note>copied message info</note> + </trans-unit> + <trans-unit id="%@, %@ and %lld members" xml:space="preserve" approved="no"> + <source>%@, %@ and %lld members</source> + <target state="translated">%@, %@ και %lld μέλη</target> + <note>No comment provided by engineer.</note> + </trans-unit> + <trans-unit id="%@, %@ and %lld other members connected" xml:space="preserve" approved="no"> + <source>%@, %@ and %lld other members connected</source> + <target state="translated">%@, %@ και %lld άλλα μέλη συνδέθηκαν</target> + <note>No comment provided by engineer.</note> + </trans-unit> </body> </file> <file original="en.lproj/SimpleX--iOS--InfoPlist.strings" source-language="en" target-language="el" datatype="plaintext"> diff --git a/apps/ios/SimpleX Localizations/en.xcloc/Localized Contents/en.xliff b/apps/ios/SimpleX Localizations/en.xcloc/Localized Contents/en.xliff index 23498b2128..b2b9cbce59 100644 --- a/apps/ios/SimpleX Localizations/en.xcloc/Localized Contents/en.xliff +++ b/apps/ios/SimpleX Localizations/en.xcloc/Localized Contents/en.xliff @@ -217,6 +217,11 @@ <target>%lld messages blocked</target> <note>No comment provided by engineer.</note> </trans-unit> + <trans-unit id="%lld messages blocked by admin" xml:space="preserve"> + <source>%lld messages blocked by admin</source> + <target>%lld messages blocked by admin</target> + <note>No comment provided by engineer.</note> + </trans-unit> <trans-unit id="%lld messages marked deleted" xml:space="preserve"> <source>%lld messages marked deleted</source> <target>%lld messages marked deleted</target> @@ -312,14 +317,19 @@ <target>)</target> <note>No comment provided by engineer.</note> </trans-unit> + <trans-unit id="**Add contact**: to create a new invitation link, or connect via a link you received." xml:space="preserve"> + <source>**Add contact**: to create a new invitation link, or connect via a link you received.</source> + <target>**Add contact**: to create a new invitation link, or connect via a link you received.</target> + <note>No comment provided by engineer.</note> + </trans-unit> <trans-unit id="**Add new contact**: to create your one-time QR Code for your contact." xml:space="preserve"> <source>**Add new contact**: to create your one-time QR Code or link for your contact.</source> <target>**Add new contact**: to create your one-time QR Code or link for your contact.</target> <note>No comment provided by engineer.</note> </trans-unit> - <trans-unit id="**Create link / QR code** for your contact to use." xml:space="preserve"> - <source>**Create link / QR code** for your contact to use.</source> - <target>**Create link / QR code** for your contact to use.</target> + <trans-unit id="**Create group**: to create a new group." xml:space="preserve"> + <source>**Create group**: to create a new group.</source> + <target>**Create group**: to create a new group.</target> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="**More private**: check new messages every 20 minutes. Device token is shared with SimpleX Chat server, but not how many contacts or messages you have." xml:space="preserve"> @@ -332,11 +342,6 @@ <target>**Most private**: do not use SimpleX Chat notifications server, check messages periodically in the background (depends on how often you use the app).</target> <note>No comment provided by engineer.</note> </trans-unit> - <trans-unit id="**Paste received link** or open it in the browser and tap **Open in mobile app**." xml:space="preserve"> - <source>**Paste received link** or open it in the browser and tap **Open in mobile app**.</source> - <target>**Paste received link** or open it in the browser and tap **Open in mobile app**.</target> - <note>No comment provided by engineer.</note> - </trans-unit> <trans-unit id="**Please note**: you will NOT be able to recover or change passphrase if you lose it." xml:space="preserve"> <source>**Please note**: you will NOT be able to recover or change passphrase if you lose it.</source> <target>**Please note**: you will NOT be able to recover or change passphrase if you lose it.</target> @@ -347,11 +352,6 @@ <target>**Recommended**: device token and notifications are sent to SimpleX Chat notification server, but not the message content, size or who it is from.</target> <note>No comment provided by engineer.</note> </trans-unit> - <trans-unit id="**Scan QR code**: to connect to your contact in person or via video call." xml:space="preserve"> - <source>**Scan QR code**: to connect to your contact in person or via video call.</source> - <target>**Scan QR code**: to connect to your contact in person or via video call.</target> - <note>No comment provided by engineer.</note> - </trans-unit> <trans-unit id="**Warning**: Instant push notifications require passphrase saved in Keychain." xml:space="preserve"> <source>**Warning**: Instant push notifications require passphrase saved in Keychain.</source> <target>**Warning**: Instant push notifications require passphrase saved in Keychain.</target> @@ -453,11 +453,6 @@ <target>1 week</target> <note>time interval</note> </trans-unit> - <trans-unit id="1-time link" xml:space="preserve"> - <source>1-time link</source> - <target>1-time link</target> - <note>No comment provided by engineer.</note> - </trans-unit> <trans-unit id="5 minutes" xml:space="preserve"> <source>5 minutes</source> <target>5 minutes</target> @@ -573,6 +568,11 @@ <target>Add address to your profile, so that your contacts can share it with other people. Profile update will be sent to your contacts.</target> <note>No comment provided by engineer.</note> </trans-unit> + <trans-unit id="Add contact" xml:space="preserve"> + <source>Add contact</source> + <target>Add contact</target> + <note>No comment provided by engineer.</note> + </trans-unit> <trans-unit id="Add preset servers" xml:space="preserve"> <source>Add preset servers</source> <target>Add preset servers</target> @@ -643,6 +643,11 @@ <target>All group members will remain connected.</target> <note>No comment provided by engineer.</note> </trans-unit> + <trans-unit id="All messages will be deleted - this cannot be undone!" xml:space="preserve"> + <source>All messages will be deleted - this cannot be undone!</source> + <target>All messages will be deleted - this cannot be undone!</target> + <note>No comment provided by engineer.</note> + </trans-unit> <trans-unit id="All messages will be deleted - this cannot be undone! The messages will be deleted ONLY for you." xml:space="preserve"> <source>All messages will be deleted - this cannot be undone! The messages will be deleted ONLY for you.</source> <target>All messages will be deleted - this cannot be undone! The messages will be deleted ONLY for you.</target> @@ -678,9 +683,9 @@ <target>Allow disappearing messages only if your contact allows it to you.</target> <note>No comment provided by engineer.</note> </trans-unit> - <trans-unit id="Allow irreversible message deletion only if your contact allows it to you." xml:space="preserve"> - <source>Allow irreversible message deletion only if your contact allows it to you.</source> - <target>Allow irreversible message deletion only if your contact allows it to you.</target> + <trans-unit id="Allow irreversible message deletion only if your contact allows it to you. (24 hours)" xml:space="preserve"> + <source>Allow irreversible message deletion only if your contact allows it to you. (24 hours)</source> + <target>Allow irreversible message deletion only if your contact allows it to you. (24 hours)</target> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="Allow message reactions only if your contact allows them." xml:space="preserve"> @@ -703,9 +708,9 @@ <target>Allow sending disappearing messages.</target> <note>No comment provided by engineer.</note> </trans-unit> - <trans-unit id="Allow to irreversibly delete sent messages." xml:space="preserve"> - <source>Allow to irreversibly delete sent messages.</source> - <target>Allow to irreversibly delete sent messages.</target> + <trans-unit id="Allow to irreversibly delete sent messages. (24 hours)" xml:space="preserve"> + <source>Allow to irreversibly delete sent messages. (24 hours)</source> + <target>Allow to irreversibly delete sent messages. (24 hours)</target> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="Allow to send files and media." xml:space="preserve"> @@ -738,9 +743,9 @@ <target>Allow your contacts to call you.</target> <note>No comment provided by engineer.</note> </trans-unit> - <trans-unit id="Allow your contacts to irreversibly delete sent messages." xml:space="preserve"> - <source>Allow your contacts to irreversibly delete sent messages.</source> - <target>Allow your contacts to irreversibly delete sent messages.</target> + <trans-unit id="Allow your contacts to irreversibly delete sent messages. (24 hours)" xml:space="preserve"> + <source>Allow your contacts to irreversibly delete sent messages. (24 hours)</source> + <target>Allow your contacts to irreversibly delete sent messages. (24 hours)</target> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="Allow your contacts to send disappearing messages." xml:space="preserve"> @@ -918,6 +923,11 @@ <target>Block</target> <note>No comment provided by engineer.</note> </trans-unit> + <trans-unit id="Block for all" xml:space="preserve"> + <source>Block for all</source> + <target>Block for all</target> + <note>No comment provided by engineer.</note> + </trans-unit> <trans-unit id="Block group members" xml:space="preserve"> <source>Block group members</source> <target>Block group members</target> @@ -928,19 +938,29 @@ <target>Block member</target> <note>No comment provided by engineer.</note> </trans-unit> + <trans-unit id="Block member for all?" xml:space="preserve"> + <source>Block member for all?</source> + <target>Block member for all?</target> + <note>No comment provided by engineer.</note> + </trans-unit> <trans-unit id="Block member?" xml:space="preserve"> <source>Block member?</source> <target>Block member?</target> <note>No comment provided by engineer.</note> </trans-unit> + <trans-unit id="Blocked by admin" xml:space="preserve"> + <source>Blocked by admin</source> + <target>Blocked by admin</target> + <note>No comment provided by engineer.</note> + </trans-unit> <trans-unit id="Both you and your contact can add message reactions." xml:space="preserve"> <source>Both you and your contact can add message reactions.</source> <target>Both you and your contact can add message reactions.</target> <note>No comment provided by engineer.</note> </trans-unit> - <trans-unit id="Both you and your contact can irreversibly delete sent messages." xml:space="preserve"> - <source>Both you and your contact can irreversibly delete sent messages.</source> - <target>Both you and your contact can irreversibly delete sent messages.</target> + <trans-unit id="Both you and your contact can irreversibly delete sent messages. (24 hours)" xml:space="preserve"> + <source>Both you and your contact can irreversibly delete sent messages. (24 hours)</source> + <target>Both you and your contact can irreversibly delete sent messages. (24 hours)</target> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="Both you and your contact can make calls." xml:space="preserve"> @@ -978,9 +998,9 @@ <target>Calls</target> <note>No comment provided by engineer.</note> </trans-unit> - <trans-unit id="Can't delete user profile!" xml:space="preserve"> - <source>Can't delete user profile!</source> - <target>Can't delete user profile!</target> + <trans-unit id="Camera not available" xml:space="preserve"> + <source>Camera not available</source> + <target>Camera not available</target> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="Can't invite contact!" xml:space="preserve"> @@ -1094,6 +1114,11 @@ <target>Chat is stopped</target> <note>No comment provided by engineer.</note> </trans-unit> + <trans-unit id="Chat is stopped. If you already used this database on another device, you should transfer it back before starting chat." xml:space="preserve"> + <source>Chat is stopped. If you already used this database on another device, you should transfer it back before starting chat.</source> + <target>Chat is stopped. If you already used this database on another device, you should transfer it back before starting chat.</target> + <note>No comment provided by engineer.</note> + </trans-unit> <trans-unit id="Chat preferences" xml:space="preserve"> <source>Chat preferences</source> <target>Chat preferences</target> @@ -1139,6 +1164,11 @@ <target>Clear conversation?</target> <note>No comment provided by engineer.</note> </trans-unit> + <trans-unit id="Clear private notes?" xml:space="preserve"> + <source>Clear private notes?</source> + <target>Clear private notes?</target> + <note>No comment provided by engineer.</note> + </trans-unit> <trans-unit id="Clear verification" xml:space="preserve"> <source>Clear verification</source> <target>Clear verification</target> @@ -1238,11 +1268,6 @@ This is your own one-time link!</target> <target>Connect via link</target> <note>No comment provided by engineer.</note> </trans-unit> - <trans-unit id="Connect via link / QR code" xml:space="preserve"> - <source>Connect via link / QR code</source> - <target>Connect via link / QR code</target> - <note>No comment provided by engineer.</note> - </trans-unit> <trans-unit id="Connect via one-time link" xml:space="preserve"> <source>Connect via one-time link</source> <target>Connect via one-time link</target> @@ -1418,11 +1443,6 @@ This is your own one-time link!</target> <target>Create new profile in [desktop app](https://simplex.chat/downloads/). 💻</target> <note>No comment provided by engineer.</note> </trans-unit> - <trans-unit id="Create one-time invitation link" xml:space="preserve"> - <source>Create one-time invitation link</source> - <target>Create one-time invitation link</target> - <note>No comment provided by engineer.</note> - </trans-unit> <trans-unit id="Create profile" xml:space="preserve"> <source>Create profile</source> <target>Create profile</target> @@ -1443,11 +1463,26 @@ This is your own one-time link!</target> <target>Create your profile</target> <note>No comment provided by engineer.</note> </trans-unit> + <trans-unit id="Created at" xml:space="preserve"> + <source>Created at</source> + <target>Created at</target> + <note>No comment provided by engineer.</note> + </trans-unit> + <trans-unit id="Created at: %@" xml:space="preserve"> + <source>Created at: %@</source> + <target>Created at: %@</target> + <note>copied message info</note> + </trans-unit> <trans-unit id="Created on %@" xml:space="preserve"> <source>Created on %@</source> <target>Created on %@</target> <note>No comment provided by engineer.</note> </trans-unit> + <trans-unit id="Creating link…" xml:space="preserve"> + <source>Creating link…</source> + <target>Creating link…</target> + <note>No comment provided by engineer.</note> + </trans-unit> <trans-unit id="Current Passcode" xml:space="preserve"> <source>Current Passcode</source> <target>Current Passcode</target> @@ -1928,6 +1963,11 @@ This cannot be undone!</target> <target>Do it later</target> <note>No comment provided by engineer.</note> </trans-unit> + <trans-unit id="Do not send history to new members." xml:space="preserve"> + <source>Do not send history to new members.</source> + <target>Do not send history to new members.</target> + <note>No comment provided by engineer.</note> + </trans-unit> <trans-unit id="Don't create address" xml:space="preserve"> <source>Don't create address</source> <target>Don't create address</target> @@ -1998,6 +2038,11 @@ This cannot be undone!</target> <target>Enable automatic message deletion?</target> <note>No comment provided by engineer.</note> </trans-unit> + <trans-unit id="Enable camera access" xml:space="preserve"> + <source>Enable camera access</source> + <target>Enable camera access</target> + <note>No comment provided by engineer.</note> + </trans-unit> <trans-unit id="Enable for all" xml:space="preserve"> <source>Enable for all</source> <target>Enable for all</target> @@ -2063,6 +2108,11 @@ This cannot be undone!</target> <target>Encrypted message or another event</target> <note>notification</note> </trans-unit> + <trans-unit id="Encrypted message: app is stopped" xml:space="preserve"> + <source>Encrypted message: app is stopped</source> + <target>Encrypted message: app is stopped</target> + <note>notification</note> + </trans-unit> <trans-unit id="Encrypted message: database error" xml:space="preserve"> <source>Encrypted message: database error</source> <target>Encrypted message: database error</target> @@ -2208,6 +2258,11 @@ This cannot be undone!</target> <target>Error creating member contact</target> <note>No comment provided by engineer.</note> </trans-unit> + <trans-unit id="Error creating message" xml:space="preserve"> + <source>Error creating message</source> + <target>Error creating message</target> + <note>No comment provided by engineer.</note> + </trans-unit> <trans-unit id="Error creating profile!" xml:space="preserve"> <source>Error creating profile!</source> <target>Error creating profile!</target> @@ -2293,6 +2348,11 @@ This cannot be undone!</target> <target>Error loading %@ servers</target> <note>No comment provided by engineer.</note> </trans-unit> + <trans-unit id="Error opening chat" xml:space="preserve"> + <source>Error opening chat</source> + <target>Error opening chat</target> + <note>No comment provided by engineer.</note> + </trans-unit> <trans-unit id="Error receiving file" xml:space="preserve"> <source>Error receiving file</source> <target>Error receiving file</target> @@ -2333,6 +2393,11 @@ This cannot be undone!</target> <target>Error saving user password</target> <note>No comment provided by engineer.</note> </trans-unit> + <trans-unit id="Error scanning code: %@" xml:space="preserve"> + <source>Error scanning code: %@</source> + <target>Error scanning code: %@</target> + <note>No comment provided by engineer.</note> + </trans-unit> <trans-unit id="Error sending email" xml:space="preserve"> <source>Error sending email</source> <target>Error sending email</target> @@ -2663,9 +2728,9 @@ This cannot be undone!</target> <target>Group members can add message reactions.</target> <note>No comment provided by engineer.</note> </trans-unit> - <trans-unit id="Group members can irreversibly delete sent messages." xml:space="preserve"> - <source>Group members can irreversibly delete sent messages.</source> - <target>Group members can irreversibly delete sent messages.</target> + <trans-unit id="Group members can irreversibly delete sent messages. (24 hours)" xml:space="preserve"> + <source>Group members can irreversibly delete sent messages. (24 hours)</source> + <target>Group members can irreversibly delete sent messages. (24 hours)</target> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="Group members can send direct messages." xml:space="preserve"> @@ -2773,6 +2838,11 @@ This cannot be undone!</target> <target>History</target> <note>No comment provided by engineer.</note> </trans-unit> + <trans-unit id="History is not sent to new members." xml:space="preserve"> + <source>History is not sent to new members.</source> + <target>History is not sent to new members.</target> + <note>No comment provided by engineer.</note> + </trans-unit> <trans-unit id="How SimpleX works" xml:space="preserve"> <source>How SimpleX works</source> <target>How SimpleX works</target> @@ -2808,11 +2878,6 @@ This cannot be undone!</target> <target>If you can't meet in person, show QR code in a video call, or share the link.</target> <note>No comment provided by engineer.</note> </trans-unit> - <trans-unit id="If you cannot meet in person, you can **scan QR code in the video call**, or your contact can share an invitation link." xml:space="preserve"> - <source>If you cannot meet in person, you can **scan QR code in the video call**, or your contact can share an invitation link.</source> - <target>If you cannot meet in person, you can **scan QR code in the video call**, or your contact can share an invitation link.</target> - <note>No comment provided by engineer.</note> - </trans-unit> <trans-unit id="If you enter this passcode when opening the app, all app data will be irreversibly removed!" xml:space="preserve"> <source>If you enter this passcode when opening the app, all app data will be irreversibly removed!</source> <target>If you enter this passcode when opening the app, all app data will be irreversibly removed!</target> @@ -2868,6 +2933,11 @@ This cannot be undone!</target> <target>Import database</target> <note>No comment provided by engineer.</note> </trans-unit> + <trans-unit id="Improved message delivery" xml:space="preserve"> + <source>Improved message delivery</source> + <target>Improved message delivery</target> + <note>No comment provided by engineer.</note> + </trans-unit> <trans-unit id="Improved privacy and security" xml:space="preserve"> <source>Improved privacy and security</source> <target>Improved privacy and security</target> @@ -2970,16 +3040,36 @@ This cannot be undone!</target> <target>Interface</target> <note>No comment provided by engineer.</note> </trans-unit> + <trans-unit id="Invalid QR code" xml:space="preserve"> + <source>Invalid QR code</source> + <target>Invalid QR code</target> + <note>No comment provided by engineer.</note> + </trans-unit> <trans-unit id="Invalid connection link" xml:space="preserve"> <source>Invalid connection link</source> <target>Invalid connection link</target> <note>No comment provided by engineer.</note> </trans-unit> + <trans-unit id="Invalid display name!" xml:space="preserve"> + <source>Invalid display name!</source> + <target>Invalid display name!</target> + <note>No comment provided by engineer.</note> + </trans-unit> + <trans-unit id="Invalid link" xml:space="preserve"> + <source>Invalid link</source> + <target>Invalid link</target> + <note>No comment provided by engineer.</note> + </trans-unit> <trans-unit id="Invalid name!" xml:space="preserve"> <source>Invalid name!</source> <target>Invalid name!</target> <note>No comment provided by engineer.</note> </trans-unit> + <trans-unit id="Invalid response" xml:space="preserve"> + <source>Invalid response</source> + <target>Invalid response</target> + <note>No comment provided by engineer.</note> + </trans-unit> <trans-unit id="Invalid server address!" xml:space="preserve"> <source>Invalid server address!</source> <target>Invalid server address!</target> @@ -3071,6 +3161,11 @@ This cannot be undone!</target> <target>Join group</target> <note>No comment provided by engineer.</note> </trans-unit> + <trans-unit id="Join group conversations" xml:space="preserve"> + <source>Join group conversations</source> + <target>Join group conversations</target> + <note>No comment provided by engineer.</note> + </trans-unit> <trans-unit id="Join group?" xml:space="preserve"> <source>Join group?</source> <target>Join group?</target> @@ -3098,11 +3193,21 @@ This is your link for group %@!</target> <target>Joining group</target> <note>No comment provided by engineer.</note> </trans-unit> + <trans-unit id="Keep" xml:space="preserve"> + <source>Keep</source> + <target>Keep</target> + <note>No comment provided by engineer.</note> + </trans-unit> <trans-unit id="Keep the app open to use it from desktop" xml:space="preserve"> <source>Keep the app open to use it from desktop</source> <target>Keep the app open to use it from desktop</target> <note>No comment provided by engineer.</note> </trans-unit> + <trans-unit id="Keep unused invitation?" xml:space="preserve"> + <source>Keep unused invitation?</source> + <target>Keep unused invitation?</target> + <note>No comment provided by engineer.</note> + </trans-unit> <trans-unit id="Keep your connections" xml:space="preserve"> <source>Keep your connections</source> <target>Keep your connections</target> @@ -3188,6 +3293,11 @@ This is your link for group %@!</target> <target>Live messages</target> <note>No comment provided by engineer.</note> </trans-unit> + <trans-unit id="Local" xml:space="preserve"> + <source>Local</source> + <target>Local</target> + <note>No comment provided by engineer.</note> + </trans-unit> <trans-unit id="Local name" xml:space="preserve"> <source>Local name</source> <target>Local name</target> @@ -3428,6 +3538,11 @@ This is your link for group %@!</target> <target>New Passcode</target> <note>No comment provided by engineer.</note> </trans-unit> + <trans-unit id="New chat" xml:space="preserve"> + <source>New chat</source> + <target>New chat</target> + <note>No comment provided by engineer.</note> + </trans-unit> <trans-unit id="New contact request" xml:space="preserve"> <source>New contact request</source> <target>New contact request</target> @@ -3552,16 +3667,16 @@ This is your link for group %@!</target> - disable members ("observer" role)</target> <note>No comment provided by engineer.</note> </trans-unit> + <trans-unit id="OK" xml:space="preserve"> + <source>OK</source> + <target>OK</target> + <note>No comment provided by engineer.</note> + </trans-unit> <trans-unit id="Off" xml:space="preserve"> <source>Off</source> <target>Off</target> <note>No comment provided by engineer.</note> </trans-unit> - <trans-unit id="Off (Local)" xml:space="preserve"> - <source>Off (Local)</source> - <target>Off (Local)</target> - <note>No comment provided by engineer.</note> - </trans-unit> <trans-unit id="Ok" xml:space="preserve"> <source>Ok</source> <target>Ok</target> @@ -3622,9 +3737,9 @@ This is your link for group %@!</target> <target>Only you can add message reactions.</target> <note>No comment provided by engineer.</note> </trans-unit> - <trans-unit id="Only you can irreversibly delete messages (your contact can mark them for deletion)." xml:space="preserve"> - <source>Only you can irreversibly delete messages (your contact can mark them for deletion).</source> - <target>Only you can irreversibly delete messages (your contact can mark them for deletion).</target> + <trans-unit id="Only you can irreversibly delete messages (your contact can mark them for deletion). (24 hours)" xml:space="preserve"> + <source>Only you can irreversibly delete messages (your contact can mark them for deletion). (24 hours)</source> + <target>Only you can irreversibly delete messages (your contact can mark them for deletion). (24 hours)</target> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="Only you can make calls." xml:space="preserve"> @@ -3647,9 +3762,9 @@ This is your link for group %@!</target> <target>Only your contact can add message reactions.</target> <note>No comment provided by engineer.</note> </trans-unit> - <trans-unit id="Only your contact can irreversibly delete messages (you can mark them for deletion)." xml:space="preserve"> - <source>Only your contact can irreversibly delete messages (you can mark them for deletion).</source> - <target>Only your contact can irreversibly delete messages (you can mark them for deletion).</target> + <trans-unit id="Only your contact can irreversibly delete messages (you can mark them for deletion). (24 hours)" xml:space="preserve"> + <source>Only your contact can irreversibly delete messages (you can mark them for deletion). (24 hours)</source> + <target>Only your contact can irreversibly delete messages (you can mark them for deletion). (24 hours)</target> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="Only your contact can make calls." xml:space="preserve"> @@ -3702,9 +3817,19 @@ This is your link for group %@!</target> <target>Open-source protocol and code – anybody can run the servers.</target> <note>No comment provided by engineer.</note> </trans-unit> - <trans-unit id="Opening database…" xml:space="preserve"> - <source>Opening database…</source> - <target>Opening database…</target> + <trans-unit id="Opening app…" xml:space="preserve"> + <source>Opening app…</source> + <target>Opening app…</target> + <note>No comment provided by engineer.</note> + </trans-unit> + <trans-unit id="Or scan QR code" xml:space="preserve"> + <source>Or scan QR code</source> + <target>Or scan QR code</target> + <note>No comment provided by engineer.</note> + </trans-unit> + <trans-unit id="Or show this code" xml:space="preserve"> + <source>Or show this code</source> + <target>Or show this code</target> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="PING count" xml:space="preserve"> @@ -3747,10 +3872,10 @@ This is your link for group %@!</target> <target>Password to show</target> <note>No comment provided by engineer.</note> </trans-unit> - <trans-unit id="Paste" xml:space="preserve"> - <source>Paste</source> - <target>Paste</target> - <note>No comment provided by engineer.</note> + <trans-unit id="Past member %@" xml:space="preserve"> + <source>Past member %@</source> + <target>Past member %@</target> + <note>past/unknown group member</note> </trans-unit> <trans-unit id="Paste desktop address" xml:space="preserve"> <source>Paste desktop address</source> @@ -3762,15 +3887,15 @@ This is your link for group %@!</target> <target>Paste image</target> <note>No comment provided by engineer.</note> </trans-unit> - <trans-unit id="Paste received link" xml:space="preserve"> - <source>Paste received link</source> - <target>Paste received link</target> + <trans-unit id="Paste link to connect!" xml:space="preserve"> + <source>Paste link to connect!</source> + <target>Paste link to connect!</target> <note>No comment provided by engineer.</note> </trans-unit> - <trans-unit id="Paste the link you received to connect with your contact." xml:space="preserve"> - <source>Paste the link you received to connect with your contact.</source> - <target>Paste the link you received to connect with your contact.</target> - <note>placeholder</note> + <trans-unit id="Paste the link you received" xml:space="preserve"> + <source>Paste the link you received</source> + <target>Paste the link you received</target> + <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="People can connect to you only via the links you share." xml:space="preserve"> <source>People can connect to you only via the links you share.</source> @@ -3807,6 +3932,13 @@ This is your link for group %@!</target> <target>Please check yours and your contact preferences.</target> <note>No comment provided by engineer.</note> </trans-unit> + <trans-unit id="Please contact developers. Error: %@" xml:space="preserve"> + <source>Please contact developers. +Error: %@</source> + <target>Please contact developers. +Error: %@</target> + <note>No comment provided by engineer.</note> + </trans-unit> <trans-unit id="Please contact group admin." xml:space="preserve"> <source>Please contact group admin.</source> <target>Please contact group admin.</target> @@ -3892,6 +4024,11 @@ This is your link for group %@!</target> <target>Private filenames</target> <note>No comment provided by engineer.</note> </trans-unit> + <trans-unit id="Private notes" xml:space="preserve"> + <source>Private notes</source> + <target>Private notes</target> + <note>name of notes to self</note> + </trans-unit> <trans-unit id="Profile and server connections" xml:space="preserve"> <source>Profile and server connections</source> <target>Profile and server connections</target> @@ -4012,6 +4149,11 @@ This is your link for group %@!</target> <target>Read more in [User Guide](https://simplex.chat/docs/guide/app-settings.html#your-simplex-contact-address).</target> <note>No comment provided by engineer.</note> </trans-unit> + <trans-unit id="Read more in [User Guide](https://simplex.chat/docs/guide/chat-profiles.html#incognito-mode)." xml:space="preserve"> + <source>Read more in [User Guide](https://simplex.chat/docs/guide/chat-profiles.html#incognito-mode).</source> + <target>Read more in [User Guide](https://simplex.chat/docs/guide/chat-profiles.html#incognito-mode).</target> + <note>No comment provided by engineer.</note> + </trans-unit> <trans-unit id="Read more in [User Guide](https://simplex.chat/docs/guide/readme.html#connect-to-friends)." xml:space="preserve"> <source>Read more in [User Guide](https://simplex.chat/docs/guide/readme.html#connect-to-friends).</source> <target>Read more in [User Guide](https://simplex.chat/docs/guide/readme.html#connect-to-friends).</target> @@ -4067,6 +4209,11 @@ This is your link for group %@!</target> <target>Receiving via</target> <note>No comment provided by engineer.</note> </trans-unit> + <trans-unit id="Recent history and improved [directory bot](simplex:/contact#/?v=1-4&smp=smp%3A%2F%2Fu2dS9sG8nMNURyZwqASV4yROM28Er0luVTx5X1CsMrU%3D%40smp4.simplex.im%2FeXSPwqTkKyDO3px4fLf1wx3MvPdjdLW3%23%2F%3Fv%3D1-2%26dh%3DMCowBQYDK2VuAyEAaiv6MkMH44L2TcYrt_CsX3ZvM11WgbMEUn0hkIKTOho%253D%26srv%3Do5vmywmrnaxalvz6wi3zicyftgio6psuvyniis6gco6bp6ekl4cqj4id.onion)." xml:space="preserve"> + <source>Recent history and improved [directory bot](simplex:/contact#/?v=1-4&smp=smp%3A%2F%2Fu2dS9sG8nMNURyZwqASV4yROM28Er0luVTx5X1CsMrU%3D%40smp4.simplex.im%2FeXSPwqTkKyDO3px4fLf1wx3MvPdjdLW3%23%2F%3Fv%3D1-2%26dh%3DMCowBQYDK2VuAyEAaiv6MkMH44L2TcYrt_CsX3ZvM11WgbMEUn0hkIKTOho%253D%26srv%3Do5vmywmrnaxalvz6wi3zicyftgio6psuvyniis6gco6bp6ekl4cqj4id.onion).</source> + <target>Recent history and improved [directory bot](simplex:/contact#/?v=1-4&smp=smp%3A%2F%2Fu2dS9sG8nMNURyZwqASV4yROM28Er0luVTx5X1CsMrU%3D%40smp4.simplex.im%2FeXSPwqTkKyDO3px4fLf1wx3MvPdjdLW3%23%2F%3Fv%3D1-2%26dh%3DMCowBQYDK2VuAyEAaiv6MkMH44L2TcYrt_CsX3ZvM11WgbMEUn0hkIKTOho%253D%26srv%3Do5vmywmrnaxalvz6wi3zicyftgio6psuvyniis6gco6bp6ekl4cqj4id.onion).</target> + <note>No comment provided by engineer.</note> + </trans-unit> <trans-unit id="Recipients see updates as you type them." xml:space="preserve"> <source>Recipients see updates as you type them.</source> <target>Recipients see updates as you type them.</target> @@ -4222,6 +4369,11 @@ This is your link for group %@!</target> <target>Restore database error</target> <note>No comment provided by engineer.</note> </trans-unit> + <trans-unit id="Retry" xml:space="preserve"> + <source>Retry</source> + <target>Retry</target> + <note>No comment provided by engineer.</note> + </trans-unit> <trans-unit id="Reveal" xml:space="preserve"> <source>Reveal</source> <target>Reveal</target> @@ -4347,6 +4499,11 @@ This is your link for group %@!</target> <target>Saved WebRTC ICE servers will be removed</target> <note>No comment provided by engineer.</note> </trans-unit> + <trans-unit id="Saved message" xml:space="preserve"> + <source>Saved message</source> + <target>Saved message</target> + <note>message info title</note> + </trans-unit> <trans-unit id="Scan QR code" xml:space="preserve"> <source>Scan QR code</source> <target>Scan QR code</target> @@ -4377,6 +4534,16 @@ This is your link for group %@!</target> <target>Search</target> <note>No comment provided by engineer.</note> </trans-unit> + <trans-unit id="Search bar accepts invitation links." xml:space="preserve"> + <source>Search bar accepts invitation links.</source> + <target>Search bar accepts invitation links.</target> + <note>No comment provided by engineer.</note> + </trans-unit> + <trans-unit id="Search or paste SimpleX link" xml:space="preserve"> + <source>Search or paste SimpleX link</source> + <target>Search or paste SimpleX link</target> + <note>No comment provided by engineer.</note> + </trans-unit> <trans-unit id="Secure queue" xml:space="preserve"> <source>Secure queue</source> <target>Secure queue</target> @@ -4482,6 +4649,11 @@ This is your link for group %@!</target> <target>Send them from gallery or custom keyboards.</target> <note>No comment provided by engineer.</note> </trans-unit> + <trans-unit id="Send up to 100 last messages to new members." xml:space="preserve"> + <source>Send up to 100 last messages to new members.</source> + <target>Send up to 100 last messages to new members.</target> + <note>No comment provided by engineer.</note> + </trans-unit> <trans-unit id="Sender cancelled file transfer." xml:space="preserve"> <source>Sender cancelled file transfer.</source> <target>Sender cancelled file transfer.</target> @@ -4652,9 +4824,9 @@ This is your link for group %@!</target> <target>Share link</target> <note>No comment provided by engineer.</note> </trans-unit> - <trans-unit id="Share one-time invitation link" xml:space="preserve"> - <source>Share one-time invitation link</source> - <target>Share one-time invitation link</target> + <trans-unit id="Share this 1-time invite link" xml:space="preserve"> + <source>Share this 1-time invite link</source> + <target>Share this 1-time invite link</target> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="Share with contacts" xml:space="preserve"> @@ -4777,16 +4949,16 @@ This is your link for group %@!</target> <target>Somebody</target> <note>notification title</note> </trans-unit> - <trans-unit id="Start a new chat" xml:space="preserve"> - <source>Start a new chat</source> - <target>Start a new chat</target> - <note>No comment provided by engineer.</note> - </trans-unit> <trans-unit id="Start chat" xml:space="preserve"> <source>Start chat</source> <target>Start chat</target> <note>No comment provided by engineer.</note> </trans-unit> + <trans-unit id="Start chat?" xml:space="preserve"> + <source>Start chat?</source> + <target>Start chat?</target> + <note>No comment provided by engineer.</note> + </trans-unit> <trans-unit id="Start migration" xml:space="preserve"> <source>Start migration</source> <target>Start migration</target> @@ -4912,6 +5084,16 @@ This is your link for group %@!</target> <target>Tap to join incognito</target> <note>No comment provided by engineer.</note> </trans-unit> + <trans-unit id="Tap to paste link" xml:space="preserve"> + <source>Tap to paste link</source> + <target>Tap to paste link</target> + <note>No comment provided by engineer.</note> + </trans-unit> + <trans-unit id="Tap to scan" xml:space="preserve"> + <source>Tap to scan</source> + <target>Tap to scan</target> + <note>No comment provided by engineer.</note> + </trans-unit> <trans-unit id="Tap to start a new chat" xml:space="preserve"> <source>Tap to start a new chat</source> <target>Tap to start a new chat</target> @@ -4974,6 +5156,11 @@ It can happen because of some bug or when the connection is compromised.</target <target>The attempt to change database passphrase was not completed.</target> <note>No comment provided by engineer.</note> </trans-unit> + <trans-unit id="The code you scanned is not a SimpleX link QR code." xml:space="preserve"> + <source>The code you scanned is not a SimpleX link QR code.</source> + <target>The code you scanned is not a SimpleX link QR code.</target> + <note>No comment provided by engineer.</note> + </trans-unit> <trans-unit id="The connection you accepted will be cancelled!" xml:space="preserve"> <source>The connection you accepted will be cancelled!</source> <target>The connection you accepted will be cancelled!</target> @@ -5039,21 +5226,16 @@ It can happen because of some bug or when the connection is compromised.</target <target>The servers for new connections of your current chat profile **%@**.</target> <note>No comment provided by engineer.</note> </trans-unit> + <trans-unit id="The text you pasted is not a SimpleX link." xml:space="preserve"> + <source>The text you pasted is not a SimpleX link.</source> + <target>The text you pasted is not a SimpleX link.</target> + <note>No comment provided by engineer.</note> + </trans-unit> <trans-unit id="Theme" xml:space="preserve"> <source>Theme</source> <target>Theme</target> <note>No comment provided by engineer.</note> </trans-unit> - <trans-unit id="There should be at least one user profile." xml:space="preserve"> - <source>There should be at least one user profile.</source> - <target>There should be at least one user profile.</target> - <note>No comment provided by engineer.</note> - </trans-unit> - <trans-unit id="There should be at least one visible user profile." xml:space="preserve"> - <source>There should be at least one visible user profile.</source> - <target>There should be at least one visible user profile.</target> - <note>No comment provided by engineer.</note> - </trans-unit> <trans-unit id="These settings are for your current profile **%@**." xml:space="preserve"> <source>These settings are for your current profile **%@**.</source> <target>These settings are for your current profile **%@**.</target> @@ -5084,6 +5266,11 @@ It can happen because of some bug or when the connection is compromised.</target <target>This device name</target> <note>No comment provided by engineer.</note> </trans-unit> + <trans-unit id="This display name is invalid. Please choose another name." xml:space="preserve"> + <source>This display name is invalid. Please choose another name.</source> + <target>This display name is invalid. Please choose another name.</target> + <note>No comment provided by engineer.</note> + </trans-unit> <trans-unit id="This group has over %lld members, delivery receipts are not sent." xml:space="preserve"> <source>This group has over %lld members, delivery receipts are not sent.</source> <target>This group has over %lld members, delivery receipts are not sent.</target> @@ -5186,16 +5373,16 @@ You will be prompted to complete authentication before this feature is enabled.< <target>Trying to connect to the server used to receive messages from this contact.</target> <note>No comment provided by engineer.</note> </trans-unit> + <trans-unit id="Turkish interface" xml:space="preserve"> + <source>Turkish interface</source> + <target>Turkish interface</target> + <note>No comment provided by engineer.</note> + </trans-unit> <trans-unit id="Turn off" xml:space="preserve"> <source>Turn off</source> <target>Turn off</target> <note>No comment provided by engineer.</note> </trans-unit> - <trans-unit id="Turn off notifications?" xml:space="preserve"> - <source>Turn off notifications?</source> - <target>Turn off notifications?</target> - <note>No comment provided by engineer.</note> - </trans-unit> <trans-unit id="Turn on" xml:space="preserve"> <source>Turn on</source> <target>Turn on</target> @@ -5211,11 +5398,21 @@ You will be prompted to complete authentication before this feature is enabled.< <target>Unblock</target> <note>No comment provided by engineer.</note> </trans-unit> + <trans-unit id="Unblock for all" xml:space="preserve"> + <source>Unblock for all</source> + <target>Unblock for all</target> + <note>No comment provided by engineer.</note> + </trans-unit> <trans-unit id="Unblock member" xml:space="preserve"> <source>Unblock member</source> <target>Unblock member</target> <note>No comment provided by engineer.</note> </trans-unit> + <trans-unit id="Unblock member for all?" xml:space="preserve"> + <source>Unblock member for all?</source> + <target>Unblock member for all?</target> + <note>No comment provided by engineer.</note> + </trans-unit> <trans-unit id="Unblock member?" xml:space="preserve"> <source>Unblock member?</source> <target>Unblock member?</target> @@ -5313,6 +5510,11 @@ To connect, please ask your contact to create another connection link and check <target>Unread</target> <note>No comment provided by engineer.</note> </trans-unit> + <trans-unit id="Up to 100 last messages are sent to new members." xml:space="preserve"> + <source>Up to 100 last messages are sent to new members.</source> + <target>Up to 100 last messages are sent to new members.</target> + <note>No comment provided by engineer.</note> + </trans-unit> <trans-unit id="Update" xml:space="preserve"> <source>Update</source> <target>Update</target> @@ -5398,6 +5600,11 @@ To connect, please ask your contact to create another connection link and check <target>Use new incognito profile</target> <note>No comment provided by engineer.</note> </trans-unit> + <trans-unit id="Use only local notifications?" xml:space="preserve"> + <source>Use only local notifications?</source> + <target>Use only local notifications?</target> + <note>No comment provided by engineer.</note> + </trans-unit> <trans-unit id="Use server" xml:space="preserve"> <source>Use server</source> <target>Use server</target> @@ -5478,6 +5685,11 @@ To connect, please ask your contact to create another connection link and check <target>View security code</target> <note>No comment provided by engineer.</note> </trans-unit> + <trans-unit id="Visible history" xml:space="preserve"> + <source>Visible history</source> + <target>Visible history</target> + <note>chat feature</note> + </trans-unit> <trans-unit id="Voice messages" xml:space="preserve"> <source>Voice messages</source> <target>Voice messages</target> @@ -5563,11 +5775,21 @@ To connect, please ask your contact to create another connection link and check <target>When you share an incognito profile with somebody, this profile will be used for the groups they invite you to.</target> <note>No comment provided by engineer.</note> </trans-unit> + <trans-unit id="With encrypted files and media." xml:space="preserve"> + <source>With encrypted files and media.</source> + <target>With encrypted files and media.</target> + <note>No comment provided by engineer.</note> + </trans-unit> <trans-unit id="With optional welcome message." xml:space="preserve"> <source>With optional welcome message.</source> <target>With optional welcome message.</target> <note>No comment provided by engineer.</note> </trans-unit> + <trans-unit id="With reduced battery usage." xml:space="preserve"> + <source>With reduced battery usage.</source> + <target>With reduced battery usage.</target> + <note>No comment provided by engineer.</note> + </trans-unit> <trans-unit id="Wrong database passphrase" xml:space="preserve"> <source>Wrong database passphrase</source> <target>Wrong database passphrase</target> @@ -5660,11 +5882,6 @@ Repeat join request?</target> <target>You can accept calls from lock screen, without device and app authentication.</target> <note>No comment provided by engineer.</note> </trans-unit> - <trans-unit id="You can also connect by clicking the link. If it opens in the browser, click **Open in mobile app** button." xml:space="preserve"> - <source>You can also connect by clicking the link. If it opens in the browser, click **Open in mobile app** button.</source> - <target>You can also connect by clicking the link. If it opens in the browser, click **Open in mobile app** button.</target> - <note>No comment provided by engineer.</note> - </trans-unit> <trans-unit id="You can create it later" xml:space="preserve"> <source>You can create it later</source> <target>You can create it later</target> @@ -5685,6 +5902,11 @@ Repeat join request?</target> <target>You can hide or mute a user profile - swipe it to the right.</target> <note>No comment provided by engineer.</note> </trans-unit> + <trans-unit id="You can make it visible to your SimpleX contacts via Settings." xml:space="preserve"> + <source>You can make it visible to your SimpleX contacts via Settings.</source> + <target>You can make it visible to your SimpleX contacts via Settings.</target> + <note>No comment provided by engineer.</note> + </trans-unit> <trans-unit id="You can now send messages to %@" xml:space="preserve"> <source>You can now send messages to %@</source> <target>You can now send messages to %@</target> @@ -5725,6 +5947,11 @@ Repeat join request?</target> <target>You can use markdown to format messages:</target> <note>No comment provided by engineer.</note> </trans-unit> + <trans-unit id="You can view invitation link again in connection details." xml:space="preserve"> + <source>You can view invitation link again in connection details.</source> + <target>You can view invitation link again in connection details.</target> + <note>No comment provided by engineer.</note> + </trans-unit> <trans-unit id="You can't send messages!" xml:space="preserve"> <source>You can't send messages!</source> <target>You can't send messages!</target> @@ -5914,13 +6141,6 @@ You can cancel this connection and remove the contact (and try later with a new <target>Your contacts can allow full message deletion.</target> <note>No comment provided by engineer.</note> </trans-unit> - <trans-unit id="Your contacts in SimpleX will see it. You can change it in Settings." xml:space="preserve"> - <source>Your contacts in SimpleX will see it. -You can change it in Settings.</source> - <target>Your contacts in SimpleX will see it. -You can change it in Settings.</target> - <note>No comment provided by engineer.</note> - </trans-unit> <trans-unit id="Your contacts will remain connected." xml:space="preserve"> <source>Your contacts will remain connected.</source> <target>Your contacts will remain connected.</target> @@ -6073,6 +6293,16 @@ SimpleX servers cannot see your profile.</target> <target>blocked</target> <note>No comment provided by engineer.</note> </trans-unit> + <trans-unit id="blocked %@" xml:space="preserve"> + <source>blocked %@</source> + <target>blocked %@</target> + <note>rcv group event chat item</note> + </trans-unit> + <trans-unit id="blocked by admin" xml:space="preserve"> + <source>blocked by admin</source> + <target>blocked by admin</target> + <note>blocked chat item</note> + </trans-unit> <trans-unit id="bold" xml:space="preserve"> <source>bold</source> <target>bold</target> @@ -6193,6 +6423,11 @@ SimpleX servers cannot see your profile.</target> <target>connection:%@</target> <note>connection information</note> </trans-unit> + <trans-unit id="contact %@ changed to %@" xml:space="preserve"> + <source>contact %1$@ changed to %2$@</source> + <target>contact %1$@ changed to %2$@</target> + <note>profile update event chat item</note> + </trans-unit> <trans-unit id="contact has e2e encryption" xml:space="preserve"> <source>contact has e2e encryption</source> <target>contact has e2e encryption</target> @@ -6463,6 +6698,11 @@ SimpleX servers cannot see your profile.</target> <target>member</target> <note>member role</note> </trans-unit> + <trans-unit id="member %@ changed to %@" xml:space="preserve"> + <source>member %1$@ changed to %2$@</source> + <target>member %1$@ changed to %2$@</target> + <note>profile update event chat item</note> + </trans-unit> <trans-unit id="member connected" xml:space="preserve"> <source>connected</source> <target>connected</target> @@ -6585,6 +6825,16 @@ SimpleX servers cannot see your profile.</target> <target>removed %@</target> <note>rcv group event chat item</note> </trans-unit> + <trans-unit id="removed contact address" xml:space="preserve"> + <source>removed contact address</source> + <target>removed contact address</target> + <note>profile update event chat item</note> + </trans-unit> + <trans-unit id="removed profile picture" xml:space="preserve"> + <source>removed profile picture</source> + <target>removed profile picture</target> + <note>profile update event chat item</note> + </trans-unit> <trans-unit id="removed you" xml:space="preserve"> <source>removed you</source> <target>removed you</target> @@ -6615,6 +6865,16 @@ SimpleX servers cannot see your profile.</target> <target>send direct message</target> <note>No comment provided by engineer.</note> </trans-unit> + <trans-unit id="set new contact address" xml:space="preserve"> + <source>set new contact address</source> + <target>set new contact address</target> + <note>profile update event chat item</note> + </trans-unit> + <trans-unit id="set new profile picture" xml:space="preserve"> + <source>set new profile picture</source> + <target>set new profile picture</target> + <note>profile update event chat item</note> + </trans-unit> <trans-unit id="starting…" xml:space="preserve"> <source>starting…</source> <target>starting…</target> @@ -6630,16 +6890,31 @@ SimpleX servers cannot see your profile.</target> <target>this contact</target> <note>notification title</note> </trans-unit> + <trans-unit id="unblocked %@" xml:space="preserve"> + <source>unblocked %@</source> + <target>unblocked %@</target> + <note>rcv group event chat item</note> + </trans-unit> <trans-unit id="unknown" xml:space="preserve"> <source>unknown</source> <target>unknown</target> <note>connection info</note> </trans-unit> + <trans-unit id="unknown status" xml:space="preserve"> + <source>unknown status</source> + <target>unknown status</target> + <note>No comment provided by engineer.</note> + </trans-unit> <trans-unit id="updated group profile" xml:space="preserve"> <source>updated group profile</source> <target>updated group profile</target> <note>rcv group event chat item</note> </trans-unit> + <trans-unit id="updated profile" xml:space="preserve"> + <source>updated profile</source> + <target>updated profile</target> + <note>profile update event chat item</note> + </trans-unit> <trans-unit id="v%@" xml:space="preserve"> <source>v%@</source> <target>v%@</target> @@ -6710,6 +6985,11 @@ SimpleX servers cannot see your profile.</target> <target>you are observer</target> <note>No comment provided by engineer.</note> </trans-unit> + <trans-unit id="you blocked %@" xml:space="preserve"> + <source>you blocked %@</source> + <target>you blocked %@</target> + <note>snd group event chat item</note> + </trans-unit> <trans-unit id="you changed address" xml:space="preserve"> <source>you changed address</source> <target>you changed address</target> @@ -6750,6 +7030,11 @@ SimpleX servers cannot see your profile.</target> <target>you shared one-time link incognito</target> <note>chat list item description</note> </trans-unit> + <trans-unit id="you unblocked %@" xml:space="preserve"> + <source>you unblocked %@</source> + <target>you unblocked %@</target> + <note>snd group event chat item</note> + </trans-unit> <trans-unit id="you: " xml:space="preserve"> <source>you: </source> <target>you: </target> diff --git a/apps/ios/SimpleX Localizations/es.xcloc/Localized Contents/es.xliff b/apps/ios/SimpleX Localizations/es.xcloc/Localized Contents/es.xliff index ccc7ee3446..bed077aa46 100644 --- a/apps/ios/SimpleX Localizations/es.xcloc/Localized Contents/es.xliff +++ b/apps/ios/SimpleX Localizations/es.xcloc/Localized Contents/es.xliff @@ -89,6 +89,7 @@ </trans-unit> <trans-unit id="%@ and %@" xml:space="preserve"> <source>%@ and %@</source> + <target>%@ y %@</target> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="%@ and %@ connected" xml:space="preserve"> @@ -103,6 +104,7 @@ </trans-unit> <trans-unit id="%@ connected" xml:space="preserve"> <source>%@ connected</source> + <target>%@ conectado</target> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="%@ is connected!" xml:space="preserve"> @@ -132,6 +134,7 @@ </trans-unit> <trans-unit id="%@, %@ and %lld members" xml:space="preserve"> <source>%@, %@ and %lld members</source> + <target>%@, %@ y %lld miembro(s) más</target> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="%@, %@ and %lld other members connected" xml:space="preserve"> @@ -201,6 +204,7 @@ </trans-unit> <trans-unit id="%lld group events" xml:space="preserve"> <source>%lld group events</source> + <target>%lld evento(s) de grupo</target> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="%lld members" xml:space="preserve"> @@ -210,14 +214,21 @@ </trans-unit> <trans-unit id="%lld messages blocked" xml:space="preserve"> <source>%lld messages blocked</source> + <target>%lld mensaje(s) bloqueado(s)</target> + <note>No comment provided by engineer.</note> + </trans-unit> + <trans-unit id="%lld messages blocked by admin" xml:space="preserve"> + <source>%lld messages blocked by admin</source> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="%lld messages marked deleted" xml:space="preserve"> <source>%lld messages marked deleted</source> + <target>%lld mensaje(s) marcado(s) eliminado(s)</target> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="%lld messages moderated by %@" xml:space="preserve"> <source>%lld messages moderated by %@</source> + <target>%lld mensaje(s) moderado(s) por %@</target> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="%lld minutes" xml:space="preserve"> @@ -292,10 +303,12 @@ </trans-unit> <trans-unit id="(new)" xml:space="preserve"> <source>(new)</source> + <target>(nuevo)</target> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="(this device v%@)" xml:space="preserve"> <source>(this device v%@)</source> + <target>(este dispositivo v%@)</target> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id=")" xml:space="preserve"> @@ -303,14 +316,19 @@ <target>)</target> <note>No comment provided by engineer.</note> </trans-unit> + <trans-unit id="**Add contact**: to create a new invitation link, or connect via a link you received." xml:space="preserve"> + <source>**Add contact**: to create a new invitation link, or connect via a link you received.</source> + <target>**Añadir contacto**: crea un enlace de invitación nuevo o usa un enlace recibido.</target> + <note>No comment provided by engineer.</note> + </trans-unit> <trans-unit id="**Add new contact**: to create your one-time QR Code for your contact." xml:space="preserve"> <source>**Add new contact**: to create your one-time QR Code or link for your contact.</source> <target>**Añadir nuevo contacto**: para crear tu código QR o enlace de un uso para tu contacto.</target> <note>No comment provided by engineer.</note> </trans-unit> - <trans-unit id="**Create link / QR code** for your contact to use." xml:space="preserve"> - <source>**Create link / QR code** for your contact to use.</source> - <target>**Crea enlace / código QR** para que tu contacto lo use.</target> + <trans-unit id="**Create group**: to create a new group." xml:space="preserve"> + <source>**Create group**: to create a new group.</source> + <target>**Crear grupo**: crea un grupo nuevo.</target> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="**More private**: check new messages every 20 minutes. Device token is shared with SimpleX Chat server, but not how many contacts or messages you have." xml:space="preserve"> @@ -323,11 +341,6 @@ <target>**Más privado**: no se usa el servidor de notificaciones de SimpleX Chat, los mensajes se comprueban periódicamente en segundo plano (dependiendo de la frecuencia con la que utilices la aplicación).</target> <note>No comment provided by engineer.</note> </trans-unit> - <trans-unit id="**Paste received link** or open it in the browser and tap **Open in mobile app**." xml:space="preserve"> - <source>**Paste received link** or open it in the browser and tap **Open in mobile app**.</source> - <target>**Pega el enlace recibido** o ábrelo en el navegador y pulsa **Abrir en aplicación móvil**.</target> - <note>No comment provided by engineer.</note> - </trans-unit> <trans-unit id="**Please note**: you will NOT be able to recover or change passphrase if you lose it." xml:space="preserve"> <source>**Please note**: you will NOT be able to recover or change passphrase if you lose it.</source> <target>**Atención**: NO podrás recuperar o cambiar la contraseña si la pierdes.</target> @@ -338,11 +351,6 @@ <target>**Recomendado**: el token del dispositivo y las notificaciones se envían al servidor de notificaciones de SimpleX Chat, pero no el contenido del mensaje, su tamaño o su procedencia.</target> <note>No comment provided by engineer.</note> </trans-unit> - <trans-unit id="**Scan QR code**: to connect to your contact in person or via video call." xml:space="preserve"> - <source>**Scan QR code**: to connect to your contact in person or via video call.</source> - <target>**Escanear código QR**: en persona para conectarte con tu contacto, o por videollamada.</target> - <note>No comment provided by engineer.</note> - </trans-unit> <trans-unit id="**Warning**: Instant push notifications require passphrase saved in Keychain." xml:space="preserve"> <source>**Warning**: Instant push notifications require passphrase saved in Keychain.</source> <target>**Advertencia**: Las notificaciones automáticas instantáneas requieren una contraseña guardada en Keychain.</target> @@ -390,6 +398,9 @@ <source>- optionally notify deleted contacts. - profile names with spaces. - and more!</source> + <target>- notificar opcionalmente a los contactos eliminados. +- nombres de perfil con espacios. +- ¡...y más!</target> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="- voice messages up to 5 minutes. - custom time to disappear. - editing history." xml:space="preserve"> @@ -408,6 +419,7 @@ </trans-unit> <trans-unit id="0 sec" xml:space="preserve"> <source>0 sec</source> + <target>0 seg</target> <note>time to disappear</note> </trans-unit> <trans-unit id="0s" xml:space="preserve"> @@ -440,11 +452,6 @@ <target>una semana</target> <note>time interval</note> </trans-unit> - <trans-unit id="1-time link" xml:space="preserve"> - <source>1-time link</source> - <target>Enlace un uso</target> - <note>No comment provided by engineer.</note> - </trans-unit> <trans-unit id="5 minutes" xml:space="preserve"> <source>5 minutes</source> <target>5 minutos</target> @@ -506,12 +513,12 @@ </trans-unit> <trans-unit id="Abort changing address" xml:space="preserve"> <source>Abort changing address</source> - <target>Cancelar cambio de dirección</target> + <target>Cancelar cambio de servidor</target> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="Abort changing address?" xml:space="preserve"> <source>Abort changing address?</source> - <target>¿Cancelar el cambio de dirección?</target> + <target>¿Cancelar el cambio de servidor?</target> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="About SimpleX" xml:space="preserve"> @@ -560,6 +567,11 @@ <target>Añade la dirección a tu perfil para que tus contactos puedan compartirla con otros. La actualización del perfil se enviará a tus contactos.</target> <note>No comment provided by engineer.</note> </trans-unit> + <trans-unit id="Add contact" xml:space="preserve"> + <source>Add contact</source> + <target>Añadir contacto</target> + <note>No comment provided by engineer.</note> + </trans-unit> <trans-unit id="Add preset servers" xml:space="preserve"> <source>Add preset servers</source> <target>Añadir servidores predefinidos</target> @@ -630,6 +642,10 @@ <target>Todos los miembros del grupo permanecerán conectados.</target> <note>No comment provided by engineer.</note> </trans-unit> + <trans-unit id="All messages will be deleted - this cannot be undone!" xml:space="preserve"> + <source>All messages will be deleted - this cannot be undone!</source> + <note>No comment provided by engineer.</note> + </trans-unit> <trans-unit id="All messages will be deleted - this cannot be undone! The messages will be deleted ONLY for you." xml:space="preserve"> <source>All messages will be deleted - this cannot be undone! The messages will be deleted ONLY for you.</source> <target>Se eliminarán todos los mensajes SOLO para tí. ¡No podrá deshacerse!</target> @@ -637,6 +653,7 @@ </trans-unit> <trans-unit id="All new messages from %@ will be hidden!" xml:space="preserve"> <source>All new messages from %@ will be hidden!</source> + <target>¡Los mensajes nuevos de %@ estarán ocultos!</target> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="All your contacts will remain connected." xml:space="preserve"> @@ -664,9 +681,9 @@ <target>Se permiten los mensajes temporales pero sólo si tu contacto también los permite para tí.</target> <note>No comment provided by engineer.</note> </trans-unit> - <trans-unit id="Allow irreversible message deletion only if your contact allows it to you." xml:space="preserve"> - <source>Allow irreversible message deletion only if your contact allows it to you.</source> - <target>Se permite la eliminación irreversible de mensajes pero sólo si tu contacto también la permite para tí.</target> + <trans-unit id="Allow irreversible message deletion only if your contact allows it to you. (24 hours)" xml:space="preserve"> + <source>Allow irreversible message deletion only if your contact allows it to you. (24 hours)</source> + <target>Se permite la eliminación irreversible de mensajes pero sólo si tu contacto también la permite para tí. (24 horas)</target> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="Allow message reactions only if your contact allows them." xml:space="preserve"> @@ -676,7 +693,7 @@ </trans-unit> <trans-unit id="Allow message reactions." xml:space="preserve"> <source>Allow message reactions.</source> - <target>Permitir reacciones a los mensajes.</target> + <target>Se permiten reacciones a los mensajes.</target> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="Allow sending direct messages to members." xml:space="preserve"> @@ -689,9 +706,9 @@ <target>Permites el envío de mensajes temporales.</target> <note>No comment provided by engineer.</note> </trans-unit> - <trans-unit id="Allow to irreversibly delete sent messages." xml:space="preserve"> - <source>Allow to irreversibly delete sent messages.</source> - <target>Se permite la eliminación irreversible de mensajes.</target> + <trans-unit id="Allow to irreversibly delete sent messages. (24 hours)" xml:space="preserve"> + <source>Allow to irreversibly delete sent messages. (24 hours)</source> + <target>Se permite la eliminación irreversible de mensajes. (24 horas)</target> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="Allow to send files and media." xml:space="preserve"> @@ -724,9 +741,9 @@ <target>Permites que tus contactos puedan llamarte.</target> <note>No comment provided by engineer.</note> </trans-unit> - <trans-unit id="Allow your contacts to irreversibly delete sent messages." xml:space="preserve"> - <source>Allow your contacts to irreversibly delete sent messages.</source> - <target>Permites a tus contactos eliminar irreversiblemente los mensajes enviados.</target> + <trans-unit id="Allow your contacts to irreversibly delete sent messages. (24 hours)" xml:space="preserve"> + <source>Allow your contacts to irreversibly delete sent messages. (24 hours)</source> + <target>Permites a tus contactos eliminar irreversiblemente los mensajes enviados. (24 horas)</target> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="Allow your contacts to send disappearing messages." xml:space="preserve"> @@ -746,10 +763,12 @@ </trans-unit> <trans-unit id="Already connecting!" xml:space="preserve"> <source>Already connecting!</source> + <target>¡Ya en proceso de conexión!</target> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="Already joining the group!" xml:space="preserve"> <source>Already joining the group!</source> + <target>¡Ya en proceso de unirte al grupo!</target> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="Always use relay" xml:space="preserve"> @@ -874,6 +893,7 @@ </trans-unit> <trans-unit id="Bad desktop address" xml:space="preserve"> <source>Bad desktop address</source> + <target>Dirección ordenador incorrecta</target> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="Bad message ID" xml:space="preserve"> @@ -888,6 +908,7 @@ </trans-unit> <trans-unit id="Better groups" xml:space="preserve"> <source>Better groups</source> + <target>Grupos mejorados</target> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="Better messages" xml:space="preserve"> @@ -897,18 +918,34 @@ </trans-unit> <trans-unit id="Block" xml:space="preserve"> <source>Block</source> + <target>Bloquear</target> + <note>No comment provided by engineer.</note> + </trans-unit> + <trans-unit id="Block for all" xml:space="preserve"> + <source>Block for all</source> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="Block group members" xml:space="preserve"> <source>Block group members</source> + <target>Bloquear miembros del grupo</target> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="Block member" xml:space="preserve"> <source>Block member</source> + <target>Bloquear miembro</target> + <note>No comment provided by engineer.</note> + </trans-unit> + <trans-unit id="Block member for all?" xml:space="preserve"> + <source>Block member for all?</source> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="Block member?" xml:space="preserve"> <source>Block member?</source> + <target>¿Bloquear miembro?</target> + <note>No comment provided by engineer.</note> + </trans-unit> + <trans-unit id="Blocked by admin" xml:space="preserve"> + <source>Blocked by admin</source> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="Both you and your contact can add message reactions." xml:space="preserve"> @@ -916,9 +953,9 @@ <target>Tanto tú como tu contacto podéis añadir reacciones a los mensajes.</target> <note>No comment provided by engineer.</note> </trans-unit> - <trans-unit id="Both you and your contact can irreversibly delete sent messages." xml:space="preserve"> - <source>Both you and your contact can irreversibly delete sent messages.</source> - <target>Tanto tú como tu contacto podéis eliminar de forma irreversible los mensajes enviados.</target> + <trans-unit id="Both you and your contact can irreversibly delete sent messages. (24 hours)" xml:space="preserve"> + <source>Both you and your contact can irreversibly delete sent messages. (24 hours)</source> + <target>Tanto tú como tu contacto podéis eliminar de forma irreversible los mensajes enviados. (24 horas)</target> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="Both you and your contact can make calls." xml:space="preserve"> @@ -956,9 +993,9 @@ <target>Llamadas</target> <note>No comment provided by engineer.</note> </trans-unit> - <trans-unit id="Can't delete user profile!" xml:space="preserve"> - <source>Can't delete user profile!</source> - <target>¡No se puede eliminar el perfil!</target> + <trans-unit id="Camera not available" xml:space="preserve"> + <source>Camera not available</source> + <target>Cámara no disponible</target> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="Can't invite contact!" xml:space="preserve"> @@ -968,7 +1005,7 @@ </trans-unit> <trans-unit id="Can't invite contacts!" xml:space="preserve"> <source>Can't invite contacts!</source> - <target>¡No se puede invitar a los contactos!</target> + <target>¡No se pueden invitar contactos!</target> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="Cancel" xml:space="preserve"> @@ -1003,7 +1040,7 @@ </trans-unit> <trans-unit id="Change member role?" xml:space="preserve"> <source>Change member role?</source> - <target>¿Cambiar el rol del miembro?</target> + <target>¿Cambiar rol?</target> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="Change passcode" xml:space="preserve"> @@ -1072,6 +1109,11 @@ <target>Chat está detenido</target> <note>No comment provided by engineer.</note> </trans-unit> + <trans-unit id="Chat is stopped. If you already used this database on another device, you should transfer it back before starting chat." xml:space="preserve"> + <source>Chat is stopped. If you already used this database on another device, you should transfer it back before starting chat.</source> + <target>Chat está detenido. Si estás usando esta base de datos en otro dispositivo, deberías transferirla de vuelta antes de iniciarlo.</target> + <note>No comment provided by engineer.</note> + </trans-unit> <trans-unit id="Chat preferences" xml:space="preserve"> <source>Chat preferences</source> <target>Preferencias de Chat</target> @@ -1117,6 +1159,10 @@ <target>¿Vaciar conversación?</target> <note>No comment provided by engineer.</note> </trans-unit> + <trans-unit id="Clear private notes?" xml:space="preserve"> + <source>Clear private notes?</source> + <note>No comment provided by engineer.</note> + </trans-unit> <trans-unit id="Clear verification" xml:space="preserve"> <source>Clear verification</source> <target>Eliminar verificación</target> @@ -1174,6 +1220,7 @@ </trans-unit> <trans-unit id="Connect automatically" xml:space="preserve"> <source>Connect automatically</source> + <target>Conectar automáticamente</target> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="Connect incognito" xml:space="preserve"> @@ -1183,24 +1230,31 @@ </trans-unit> <trans-unit id="Connect to desktop" xml:space="preserve"> <source>Connect to desktop</source> + <target>Conectar con ordenador</target> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="Connect to yourself?" xml:space="preserve"> <source>Connect to yourself?</source> + <target>¿Conectarte a tí mismo?</target> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="Connect to yourself? This is your own SimpleX address!" xml:space="preserve"> <source>Connect to yourself? This is your own SimpleX address!</source> + <target>¿Conectarte a tí mismo? +¡Esta es tu propia dirección SimpleX!</target> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="Connect to yourself? This is your own one-time link!" xml:space="preserve"> <source>Connect to yourself? This is your own one-time link!</source> + <target>¿Conectarte a tí mismo? +¡Este es tu propio enlace de un solo uso!</target> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="Connect via contact address" xml:space="preserve"> <source>Connect via contact address</source> + <target>Conectar mediante dirección de contacto</target> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="Connect via link" xml:space="preserve"> @@ -1208,11 +1262,6 @@ This is your own one-time link!</source> <target>Conectar mediante enlace</target> <note>No comment provided by engineer.</note> </trans-unit> - <trans-unit id="Connect via link / QR code" xml:space="preserve"> - <source>Connect via link / QR code</source> - <target>Conecta vía enlace / Código QR</target> - <note>No comment provided by engineer.</note> - </trans-unit> <trans-unit id="Connect via one-time link" xml:space="preserve"> <source>Connect via one-time link</source> <target>Conectar mediante enlace de un sólo uso</target> @@ -1220,14 +1269,17 @@ This is your own one-time link!</source> </trans-unit> <trans-unit id="Connect with %@" xml:space="preserve"> <source>Connect with %@</source> + <target>Conectar con %@</target> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="Connected desktop" xml:space="preserve"> <source>Connected desktop</source> + <target>Ordenador conectado</target> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="Connected to desktop" xml:space="preserve"> <source>Connected to desktop</source> + <target>Conectado con ordenador</target> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="Connecting server…" xml:space="preserve"> @@ -1242,6 +1294,7 @@ This is your own one-time link!</source> </trans-unit> <trans-unit id="Connecting to desktop" xml:space="preserve"> <source>Connecting to desktop</source> + <target>Conectando con ordenador</target> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="Connection" xml:space="preserve"> @@ -1266,6 +1319,7 @@ This is your own one-time link!</source> </trans-unit> <trans-unit id="Connection terminated" xml:space="preserve"> <source>Connection terminated</source> + <target>Conexión finalizada</target> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="Connection timeout" xml:space="preserve"> @@ -1335,6 +1389,7 @@ This is your own one-time link!</source> </trans-unit> <trans-unit id="Correct name to %@?" xml:space="preserve"> <source>Correct name to %@?</source> + <target>¿Corregir el nombre a %@?</target> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="Create" xml:space="preserve"> @@ -1344,11 +1399,12 @@ This is your own one-time link!</source> </trans-unit> <trans-unit id="Create SimpleX address" xml:space="preserve"> <source>Create SimpleX address</source> - <target>Crear tu dirección SimpleX</target> + <target>Crear dirección SimpleX</target> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="Create a group using a random profile." xml:space="preserve"> <source>Create a group using a random profile.</source> + <target>Crear grupo usando perfil aleatorio.</target> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="Create an address to let people connect with you." xml:space="preserve"> @@ -1363,6 +1419,7 @@ This is your own one-time link!</source> </trans-unit> <trans-unit id="Create group" xml:space="preserve"> <source>Create group</source> + <target>Crear grupo</target> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="Create group link" xml:space="preserve"> @@ -1380,13 +1437,9 @@ This is your own one-time link!</source> <target>Crea perfil nuevo en la [aplicación para PC](https://simplex.Descargas/de chat/). 💻</target> <note>No comment provided by engineer.</note> </trans-unit> - <trans-unit id="Create one-time invitation link" xml:space="preserve"> - <source>Create one-time invitation link</source> - <target>Crea enlace de invitación de un uso</target> - <note>No comment provided by engineer.</note> - </trans-unit> <trans-unit id="Create profile" xml:space="preserve"> <source>Create profile</source> + <target>Crear perfil</target> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="Create queue" xml:space="preserve"> @@ -1404,11 +1457,24 @@ This is your own one-time link!</source> <target>Crea tu perfil</target> <note>No comment provided by engineer.</note> </trans-unit> + <trans-unit id="Created at" xml:space="preserve"> + <source>Created at</source> + <note>No comment provided by engineer.</note> + </trans-unit> + <trans-unit id="Created at: %@" xml:space="preserve"> + <source>Created at: %@</source> + <note>copied message info</note> + </trans-unit> <trans-unit id="Created on %@" xml:space="preserve"> <source>Created on %@</source> <target>Creado en %@</target> <note>No comment provided by engineer.</note> </trans-unit> + <trans-unit id="Creating link…" xml:space="preserve"> + <source>Creating link…</source> + <target>Creando enlace…</target> + <note>No comment provided by engineer.</note> + </trans-unit> <trans-unit id="Current Passcode" xml:space="preserve"> <source>Current Passcode</source> <target>Código de Acceso</target> @@ -1549,6 +1615,7 @@ This is your own one-time link!</source> </trans-unit> <trans-unit id="Delete %lld messages?" xml:space="preserve"> <source>Delete %lld messages?</source> + <target>¿Elimina %lld mensajes?</target> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="Delete Contact" xml:space="preserve"> @@ -1578,6 +1645,7 @@ This is your own one-time link!</source> </trans-unit> <trans-unit id="Delete and notify contact" xml:space="preserve"> <source>Delete and notify contact</source> + <target>Eliminar y notificar contacto</target> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="Delete archive" xml:space="preserve"> @@ -1613,6 +1681,8 @@ This is your own one-time link!</source> <trans-unit id="Delete contact? This cannot be undone!" xml:space="preserve"> <source>Delete contact? This cannot be undone!</source> + <target>¿Eliminar contacto? +¡No podrá deshacerse!</target> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="Delete database" xml:space="preserve"> @@ -1707,7 +1777,7 @@ This cannot be undone!</source> </trans-unit> <trans-unit id="Delete pending connection?" xml:space="preserve"> <source>Delete pending connection?</source> - <target>¿Eliminar la conexion pendiente?</target> + <target>¿Eliminar conexión pendiente?</target> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="Delete profile" xml:space="preserve"> @@ -1757,14 +1827,17 @@ This cannot be undone!</source> </trans-unit> <trans-unit id="Desktop address" xml:space="preserve"> <source>Desktop address</source> + <target>Dirección ordenador</target> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="Desktop app version %@ is not compatible with this app." xml:space="preserve"> <source>Desktop app version %@ is not compatible with this app.</source> + <target>La versión de aplicación del ordenador %" no es compatible con esta aplicación.</target> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="Desktop devices" xml:space="preserve"> <source>Desktop devices</source> + <target>Ordenadores</target> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="Develop" xml:space="preserve"> @@ -1859,6 +1932,7 @@ This cannot be undone!</source> </trans-unit> <trans-unit id="Disconnect desktop?" xml:space="preserve"> <source>Disconnect desktop?</source> + <target>¿Desconectar ordenador?</target> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="Discover and join groups" xml:space="preserve"> @@ -1868,6 +1942,7 @@ This cannot be undone!</source> </trans-unit> <trans-unit id="Discover via local network" xml:space="preserve"> <source>Discover via local network</source> + <target>Descubrir en red local</target> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="Do NOT use SimpleX for emergency calls." xml:space="preserve"> @@ -1880,6 +1955,10 @@ This cannot be undone!</source> <target>Hacer más tarde</target> <note>No comment provided by engineer.</note> </trans-unit> + <trans-unit id="Do not send history to new members." xml:space="preserve"> + <source>Do not send history to new members.</source> + <note>No comment provided by engineer.</note> + </trans-unit> <trans-unit id="Don't create address" xml:space="preserve"> <source>Don't create address</source> <target>No crear dirección SimpleX</target> @@ -1950,6 +2029,11 @@ This cannot be undone!</source> <target>¿Activar eliminación automática de mensajes?</target> <note>No comment provided by engineer.</note> </trans-unit> + <trans-unit id="Enable camera access" xml:space="preserve"> + <source>Enable camera access</source> + <target>Permitir acceso a la cámara</target> + <note>No comment provided by engineer.</note> + </trans-unit> <trans-unit id="Enable for all" xml:space="preserve"> <source>Enable for all</source> <target>Activar para todos</target> @@ -2015,6 +2099,11 @@ This cannot be undone!</source> <target>Mensaje cifrado u otro evento</target> <note>notification</note> </trans-unit> + <trans-unit id="Encrypted message: app is stopped" xml:space="preserve"> + <source>Encrypted message: app is stopped</source> + <target>Mensaje cifrado: la aplicación está parada</target> + <note>notification</note> + </trans-unit> <trans-unit id="Encrypted message: database error" xml:space="preserve"> <source>Encrypted message: database error</source> <target>Mensaje cifrado: error base de datos</target> @@ -2042,10 +2131,12 @@ This cannot be undone!</source> </trans-unit> <trans-unit id="Encryption re-negotiation error" xml:space="preserve"> <source>Encryption re-negotiation error</source> + <target>Error de renegociación de cifrado</target> <note>message decrypt error item</note> </trans-unit> <trans-unit id="Encryption re-negotiation failed." xml:space="preserve"> <source>Encryption re-negotiation failed.</source> + <target>Renegociación de cifrado fallida.</target> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="Enter Passcode" xml:space="preserve"> @@ -2060,6 +2151,7 @@ This cannot be undone!</source> </trans-unit> <trans-unit id="Enter group name…" xml:space="preserve"> <source>Enter group name…</source> + <target>Nombre del grupo…</target> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="Enter passphrase…" xml:space="preserve"> @@ -2079,6 +2171,7 @@ This cannot be undone!</source> </trans-unit> <trans-unit id="Enter this device name…" xml:space="preserve"> <source>Enter this device name…</source> + <target>Nombre de este dispositivo…</target> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="Enter welcome message…" xml:space="preserve"> @@ -2093,6 +2186,7 @@ This cannot be undone!</source> </trans-unit> <trans-unit id="Enter your name…" xml:space="preserve"> <source>Enter your name…</source> + <target>Introduce tu nombre…</target> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="Error" xml:space="preserve"> @@ -2122,7 +2216,7 @@ This cannot be undone!</source> </trans-unit> <trans-unit id="Error changing address" xml:space="preserve"> <source>Error changing address</source> - <target>Error al cambiar dirección</target> + <target>Error al cambiar servidor</target> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="Error changing role" xml:space="preserve"> @@ -2155,6 +2249,10 @@ This cannot be undone!</source> <target>Error al establecer contacto con el miembro</target> <note>No comment provided by engineer.</note> </trans-unit> + <trans-unit id="Error creating message" xml:space="preserve"> + <source>Error creating message</source> + <note>No comment provided by engineer.</note> + </trans-unit> <trans-unit id="Error creating profile!" xml:space="preserve"> <source>Error creating profile!</source> <target>¡Error al crear perfil!</target> @@ -2232,7 +2330,7 @@ This cannot be undone!</source> </trans-unit> <trans-unit id="Error joining group" xml:space="preserve"> <source>Error joining group</source> - <target>Error al unirse al grupo</target> + <target>Error al unirte al grupo</target> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="Error loading %@ servers" xml:space="preserve"> @@ -2240,6 +2338,11 @@ This cannot be undone!</source> <target>Error al cargar servidores %@</target> <note>No comment provided by engineer.</note> </trans-unit> + <trans-unit id="Error opening chat" xml:space="preserve"> + <source>Error opening chat</source> + <target>Error al abrir chat</target> + <note>No comment provided by engineer.</note> + </trans-unit> <trans-unit id="Error receiving file" xml:space="preserve"> <source>Error receiving file</source> <target>Error al recibir archivo</target> @@ -2280,6 +2383,11 @@ This cannot be undone!</source> <target>Error al guardar contraseña de usuario</target> <note>No comment provided by engineer.</note> </trans-unit> + <trans-unit id="Error scanning code: %@" xml:space="preserve"> + <source>Error scanning code: %@</source> + <target>Error al escanear código: %@</target> + <note>No comment provided by engineer.</note> + </trans-unit> <trans-unit id="Error sending email" xml:space="preserve"> <source>Error sending email</source> <target>Error al enviar email</target> @@ -2372,6 +2480,7 @@ This cannot be undone!</source> </trans-unit> <trans-unit id="Expand" xml:space="preserve"> <source>Expand</source> + <target>Expandir</target> <note>chat item action</note> </trans-unit> <trans-unit id="Export database" xml:space="preserve"> @@ -2406,6 +2515,7 @@ This cannot be undone!</source> </trans-unit> <trans-unit id="Faster joining and more reliable messages." xml:space="preserve"> <source>Faster joining and more reliable messages.</source> + <target>Mensajería más segura y conexión más rápida.</target> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="Favorite" xml:space="preserve"> @@ -2505,6 +2615,7 @@ This cannot be undone!</source> </trans-unit> <trans-unit id="Found desktop" xml:space="preserve"> <source>Found desktop</source> + <target>Ordenador encontrado</target> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="French interface" xml:space="preserve"> @@ -2529,6 +2640,7 @@ This cannot be undone!</source> </trans-unit> <trans-unit id="Fully decentralized – visible only to members." xml:space="preserve"> <source>Fully decentralized – visible only to members.</source> + <target>Completamente descentralizado: sólo visible a los miembros.</target> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="Fully re-implemented - work in background!" xml:space="preserve"> @@ -2553,10 +2665,12 @@ This cannot be undone!</source> </trans-unit> <trans-unit id="Group already exists" xml:space="preserve"> <source>Group already exists</source> + <target>El grupo ya existe</target> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="Group already exists!" xml:space="preserve"> <source>Group already exists!</source> + <target>¡El grupo ya existe!</target> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="Group display name" xml:space="preserve"> @@ -2604,9 +2718,9 @@ This cannot be undone!</source> <target>Los miembros pueden añadir reacciones a los mensajes.</target> <note>No comment provided by engineer.</note> </trans-unit> - <trans-unit id="Group members can irreversibly delete sent messages." xml:space="preserve"> - <source>Group members can irreversibly delete sent messages.</source> - <target>Los miembros del grupo pueden eliminar mensajes de forma irreversible.</target> + <trans-unit id="Group members can irreversibly delete sent messages. (24 hours)" xml:space="preserve"> + <source>Group members can irreversibly delete sent messages. (24 hours)</source> + <target>Los miembros del grupo pueden eliminar mensajes de forma irreversible. (24 horas)</target> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="Group members can send direct messages." xml:space="preserve"> @@ -2641,7 +2755,7 @@ This cannot be undone!</source> </trans-unit> <trans-unit id="Group preferences" xml:space="preserve"> <source>Group preferences</source> - <target>Preferencias de grupo</target> + <target>Preferencias del grupo</target> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="Group profile" xml:space="preserve"> @@ -2714,6 +2828,10 @@ This cannot be undone!</source> <target>Historial</target> <note>No comment provided by engineer.</note> </trans-unit> + <trans-unit id="History is not sent to new members." xml:space="preserve"> + <source>History is not sent to new members.</source> + <note>No comment provided by engineer.</note> + </trans-unit> <trans-unit id="How SimpleX works" xml:space="preserve"> <source>How SimpleX works</source> <target>Cómo funciona SimpleX</target> @@ -2749,11 +2867,6 @@ This cannot be undone!</source> <target>Si no puedes reunirte en persona, muestra el código QR por videollamada, o comparte el enlace.</target> <note>No comment provided by engineer.</note> </trans-unit> - <trans-unit id="If you cannot meet in person, you can **scan QR code in the video call**, or your contact can share an invitation link." xml:space="preserve"> - <source>If you cannot meet in person, you can **scan QR code in the video call**, or your contact can share an invitation link.</source> - <target>Si no puedes reunirte en persona, puedes **escanear el código QR por videollamada**, o tu contacto puede compartir un enlace de invitación.</target> - <note>No comment provided by engineer.</note> - </trans-unit> <trans-unit id="If you enter this passcode when opening the app, all app data will be irreversibly removed!" xml:space="preserve"> <source>If you enter this passcode when opening the app, all app data will be irreversibly removed!</source> <target>¡Si introduces este código al abrir la aplicación, todos los datos de la misma se eliminarán de forma irreversible!</target> @@ -2809,6 +2922,10 @@ This cannot be undone!</source> <target>Importar base de datos</target> <note>No comment provided by engineer.</note> </trans-unit> + <trans-unit id="Improved message delivery" xml:space="preserve"> + <source>Improved message delivery</source> + <note>No comment provided by engineer.</note> + </trans-unit> <trans-unit id="Improved privacy and security" xml:space="preserve"> <source>Improved privacy and security</source> <target>Seguridad y privacidad mejoradas</target> @@ -2831,6 +2948,7 @@ This cannot be undone!</source> </trans-unit> <trans-unit id="Incognito groups" xml:space="preserve"> <source>Incognito groups</source> + <target>Grupos incógnito</target> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="Incognito mode" xml:space="preserve"> @@ -2865,6 +2983,7 @@ This cannot be undone!</source> </trans-unit> <trans-unit id="Incompatible version" xml:space="preserve"> <source>Incompatible version</source> + <target>Versión incompatible</target> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="Incorrect passcode" xml:space="preserve"> @@ -2909,13 +3028,33 @@ This cannot be undone!</source> <target>Interfaz</target> <note>No comment provided by engineer.</note> </trans-unit> + <trans-unit id="Invalid QR code" xml:space="preserve"> + <source>Invalid QR code</source> + <target>Código QR no válido</target> + <note>No comment provided by engineer.</note> + </trans-unit> <trans-unit id="Invalid connection link" xml:space="preserve"> <source>Invalid connection link</source> <target>Enlace de conexión no válido</target> <note>No comment provided by engineer.</note> </trans-unit> + <trans-unit id="Invalid display name!" xml:space="preserve"> + <source>Invalid display name!</source> + <note>No comment provided by engineer.</note> + </trans-unit> + <trans-unit id="Invalid link" xml:space="preserve"> + <source>Invalid link</source> + <target>Enlace no válido</target> + <note>No comment provided by engineer.</note> + </trans-unit> <trans-unit id="Invalid name!" xml:space="preserve"> <source>Invalid name!</source> + <target>¡Nombre no válido!</target> + <note>No comment provided by engineer.</note> + </trans-unit> + <trans-unit id="Invalid response" xml:space="preserve"> + <source>Invalid response</source> + <target>Respuesta no válida</target> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="Invalid server address!" xml:space="preserve"> @@ -3001,30 +3140,38 @@ This cannot be undone!</source> </trans-unit> <trans-unit id="Join" xml:space="preserve"> <source>Join</source> - <target>Únete</target> + <target>Unirte</target> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="Join group" xml:space="preserve"> <source>Join group</source> - <target>Únete al grupo</target> + <target>Unirte al grupo</target> + <note>No comment provided by engineer.</note> + </trans-unit> + <trans-unit id="Join group conversations" xml:space="preserve"> + <source>Join group conversations</source> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="Join group?" xml:space="preserve"> <source>Join group?</source> + <target>¿Unirte al grupo?</target> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="Join incognito" xml:space="preserve"> <source>Join incognito</source> - <target>Únete en modo incógnito</target> + <target>Unirte en modo incógnito</target> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="Join with current profile" xml:space="preserve"> <source>Join with current profile</source> + <target>Unirte con el perfil actual</target> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="Join your group? This is your link for group %@!" xml:space="preserve"> <source>Join your group? This is your link for group %@!</source> + <target>¿Unirse a tu grupo? +¡Este es tu enlace para el grupo %@!</target> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="Joining group" xml:space="preserve"> @@ -3032,8 +3179,19 @@ This is your link for group %@!</source> <target>Entrando al grupo</target> <note>No comment provided by engineer.</note> </trans-unit> + <trans-unit id="Keep" xml:space="preserve"> + <source>Keep</source> + <target>Guardar</target> + <note>No comment provided by engineer.</note> + </trans-unit> <trans-unit id="Keep the app open to use it from desktop" xml:space="preserve"> <source>Keep the app open to use it from desktop</source> + <target>Mantén la aplicación abierta para usarla desde el ordenador</target> + <note>No comment provided by engineer.</note> + </trans-unit> + <trans-unit id="Keep unused invitation?" xml:space="preserve"> + <source>Keep unused invitation?</source> + <target>¿Guardar invitación no usada?</target> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="Keep your connections" xml:space="preserve"> @@ -3098,14 +3256,17 @@ This is your link for group %@!</source> </trans-unit> <trans-unit id="Link mobile and desktop apps! 🔗" xml:space="preserve"> <source>Link mobile and desktop apps! 🔗</source> + <target>¡Enlazar aplicación móvil con ordenador! 🔗</target> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="Linked desktop options" xml:space="preserve"> <source>Linked desktop options</source> + <target>Opciones ordenador enlazado</target> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="Linked desktops" xml:space="preserve"> <source>Linked desktops</source> + <target>Ordenadores enlazados</target> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="Live message!" xml:space="preserve"> @@ -3118,6 +3279,11 @@ This is your link for group %@!</source> <target>Mensajes en vivo</target> <note>No comment provided by engineer.</note> </trans-unit> + <trans-unit id="Local" xml:space="preserve"> + <source>Local</source> + <target>Local</target> + <note>No comment provided by engineer.</note> + </trans-unit> <trans-unit id="Local name" xml:space="preserve"> <source>Local name</source> <target>Nombre local</target> @@ -3200,12 +3366,12 @@ This is your link for group %@!</source> </trans-unit> <trans-unit id="Member role will be changed to "%@". All group members will be notified." xml:space="preserve"> <source>Member role will be changed to "%@". All group members will be notified.</source> - <target>El rol de miembro cambiará a "%@". Todos los miembros del grupo serán notificados.</target> + <target>El rol del miembro cambiará a "%@" y se notificará al grupo.</target> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="Member role will be changed to "%@". The member will receive a new invitation." xml:space="preserve"> <source>Member role will be changed to "%@". The member will receive a new invitation.</source> - <target>El rol del miembro cambiará a "%@". El miembro recibirá una invitación nueva.</target> + <target>El rol del miembro cambiará a "%@" y recibirá una invitación nueva.</target> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="Member will be removed from group - this cannot be undone!" xml:space="preserve"> @@ -3230,7 +3396,7 @@ This is your link for group %@!</source> </trans-unit> <trans-unit id="Message reactions" xml:space="preserve"> <source>Message reactions</source> - <target>Reacciones a los mensajes</target> + <target>Reacciones a mensajes</target> <note>chat feature</note> </trans-unit> <trans-unit id="Message reactions are prohibited in this chat." xml:space="preserve"> @@ -3260,6 +3426,7 @@ This is your link for group %@!</source> </trans-unit> <trans-unit id="Messages from %@ will be shown!" xml:space="preserve"> <source>Messages from %@ will be shown!</source> + <target>¡Los mensajes de %@ serán mostrados!</target> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="Migrating database archive…" xml:space="preserve"> @@ -3357,6 +3524,11 @@ This is your link for group %@!</source> <target>Código Nuevo</target> <note>No comment provided by engineer.</note> </trans-unit> + <trans-unit id="New chat" xml:space="preserve"> + <source>New chat</source> + <target>Nuevo chat</target> + <note>No comment provided by engineer.</note> + </trans-unit> <trans-unit id="New contact request" xml:space="preserve"> <source>New contact request</source> <target>Nueva solicitud de contacto</target> @@ -3459,6 +3631,7 @@ This is your link for group %@!</source> </trans-unit> <trans-unit id="Not compatible!" xml:space="preserve"> <source>Not compatible!</source> + <target>¡No compatible!</target> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="Notifications" xml:space="preserve"> @@ -3480,16 +3653,16 @@ This is your link for group %@!</source> - desactivar el rol miembro (a rol "observador")</target> <note>No comment provided by engineer.</note> </trans-unit> + <trans-unit id="OK" xml:space="preserve"> + <source>OK</source> + <target>OK</target> + <note>No comment provided by engineer.</note> + </trans-unit> <trans-unit id="Off" xml:space="preserve"> <source>Off</source> <target>Desactivado</target> <note>No comment provided by engineer.</note> </trans-unit> - <trans-unit id="Off (Local)" xml:space="preserve"> - <source>Off (Local)</source> - <target>Desactivado (Local)</target> - <note>No comment provided by engineer.</note> - </trans-unit> <trans-unit id="Ok" xml:space="preserve"> <source>Ok</source> <target>Ok</target> @@ -3532,7 +3705,7 @@ This is your link for group %@!</source> </trans-unit> <trans-unit id="Only group owners can change group preferences." xml:space="preserve"> <source>Only group owners can change group preferences.</source> - <target>Sólo los propietarios pueden modificar las preferencias de grupo.</target> + <target>Sólo los propietarios pueden modificar las preferencias del grupo.</target> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="Only group owners can enable files and media." xml:space="preserve"> @@ -3550,9 +3723,9 @@ This is your link for group %@!</source> <target>Sólo tú puedes añadir reacciones a los mensajes.</target> <note>No comment provided by engineer.</note> </trans-unit> - <trans-unit id="Only you can irreversibly delete messages (your contact can mark them for deletion)." xml:space="preserve"> - <source>Only you can irreversibly delete messages (your contact can mark them for deletion).</source> - <target>Sólo tú puedes eliminar mensajes de forma irreversible (tu contacto puede marcarlos para eliminar).</target> + <trans-unit id="Only you can irreversibly delete messages (your contact can mark them for deletion). (24 hours)" xml:space="preserve"> + <source>Only you can irreversibly delete messages (your contact can mark them for deletion). (24 hours)</source> + <target>Sólo tú puedes eliminar mensajes de forma irreversible (tu contacto puede marcarlos para eliminar). (24 horas)</target> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="Only you can make calls." xml:space="preserve"> @@ -3575,9 +3748,9 @@ This is your link for group %@!</source> <target>Sólo tu contacto puede añadir reacciones a los mensajes.</target> <note>No comment provided by engineer.</note> </trans-unit> - <trans-unit id="Only your contact can irreversibly delete messages (you can mark them for deletion)." xml:space="preserve"> - <source>Only your contact can irreversibly delete messages (you can mark them for deletion).</source> - <target>Sólo tu contacto puede eliminar mensajes de forma irreversible (tu puedes marcarlos para eliminar).</target> + <trans-unit id="Only your contact can irreversibly delete messages (you can mark them for deletion). (24 hours)" xml:space="preserve"> + <source>Only your contact can irreversibly delete messages (you can mark them for deletion). (24 hours)</source> + <target>Sólo tu contacto puede eliminar mensajes de forma irreversible (tu puedes marcarlos para eliminar). (24 horas)</target> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="Only your contact can make calls." xml:space="preserve"> @@ -3617,6 +3790,7 @@ This is your link for group %@!</source> </trans-unit> <trans-unit id="Open group" xml:space="preserve"> <source>Open group</source> + <target>Grupo abierto</target> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="Open user profiles" xml:space="preserve"> @@ -3629,9 +3803,19 @@ This is your link for group %@!</source> <target>Protocolo y código abiertos: cualquiera puede usar los servidores.</target> <note>No comment provided by engineer.</note> </trans-unit> - <trans-unit id="Opening database…" xml:space="preserve"> - <source>Opening database…</source> - <target>Abriendo base de datos…</target> + <trans-unit id="Opening app…" xml:space="preserve"> + <source>Opening app…</source> + <target>Iniciando aplicación…</target> + <note>No comment provided by engineer.</note> + </trans-unit> + <trans-unit id="Or scan QR code" xml:space="preserve"> + <source>Or scan QR code</source> + <target>O escanear código QR</target> + <note>No comment provided by engineer.</note> + </trans-unit> + <trans-unit id="Or show this code" xml:space="preserve"> + <source>Or show this code</source> + <target>O mostrar este código</target> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="PING count" xml:space="preserve"> @@ -3674,13 +3858,13 @@ This is your link for group %@!</source> <target>Contraseña para hacerlo visible</target> <note>No comment provided by engineer.</note> </trans-unit> - <trans-unit id="Paste" xml:space="preserve"> - <source>Paste</source> - <target>Pegar</target> - <note>No comment provided by engineer.</note> + <trans-unit id="Past member %@" xml:space="preserve"> + <source>Past member %@</source> + <note>past/unknown group member</note> </trans-unit> <trans-unit id="Paste desktop address" xml:space="preserve"> <source>Paste desktop address</source> + <target>Pegar dirección de ordenador</target> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="Paste image" xml:space="preserve"> @@ -3688,15 +3872,14 @@ This is your link for group %@!</source> <target>Pegar imagen</target> <note>No comment provided by engineer.</note> </trans-unit> - <trans-unit id="Paste received link" xml:space="preserve"> - <source>Paste received link</source> - <target>Pegar enlace recibido</target> + <trans-unit id="Paste link to connect!" xml:space="preserve"> + <source>Paste link to connect!</source> <note>No comment provided by engineer.</note> </trans-unit> - <trans-unit id="Paste the link you received to connect with your contact." xml:space="preserve"> - <source>Paste the link you received to connect with your contact.</source> - <target>Pega el enlace que has recibido en el recuadro para conectar con tu contacto.</target> - <note>placeholder</note> + <trans-unit id="Paste the link you received" xml:space="preserve"> + <source>Paste the link you received</source> + <target>Pegar el enlace recibido</target> + <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="People can connect to you only via the links you share." xml:space="preserve"> <source>People can connect to you only via the links you share.</source> @@ -3733,9 +3916,16 @@ This is your link for group %@!</source> <target>Comprueba tus preferencias y las de tu contacto.</target> <note>No comment provided by engineer.</note> </trans-unit> + <trans-unit id="Please contact developers. Error: %@" xml:space="preserve"> + <source>Please contact developers. +Error: %@</source> + <target>Por favor, contacta con los desarrolladores. +Error: %@</target> + <note>No comment provided by engineer.</note> + </trans-unit> <trans-unit id="Please contact group admin." xml:space="preserve"> <source>Please contact group admin.</source> - <target>Póngase en contacto con el administrador del grupo.</target> + <target>Ponte en contacto con el administrador del grupo.</target> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="Please enter correct current passphrase." xml:space="preserve"> @@ -3818,6 +4008,10 @@ This is your link for group %@!</source> <target>Nombres de archivos privados</target> <note>No comment provided by engineer.</note> </trans-unit> + <trans-unit id="Private notes" xml:space="preserve"> + <source>Private notes</source> + <note>name of notes to self</note> + </trans-unit> <trans-unit id="Profile and server connections" xml:space="preserve"> <source>Profile and server connections</source> <target>Perfil y conexiones de servidor</target> @@ -3830,10 +4024,12 @@ This is your link for group %@!</source> </trans-unit> <trans-unit id="Profile name" xml:space="preserve"> <source>Profile name</source> + <target>Nombre del perfil</target> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="Profile name:" xml:space="preserve"> <source>Profile name:</source> + <target>Nombre del perfil:</target> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="Profile password" xml:space="preserve"> @@ -3933,22 +4129,27 @@ This is your link for group %@!</source> </trans-unit> <trans-unit id="Read more in [User Guide](https://simplex.chat/docs/guide/app-settings.html#your-simplex-contact-address)." xml:space="preserve"> <source>Read more in [User Guide](https://simplex.chat/docs/guide/app-settings.html#your-simplex-contact-address).</source> - <target>Más información en el [Manual de usuario](https://simplex.chat/docs/guide/app-settings.html#your-simplex-contact-address).</target> + <target>Saber más en el [Manual del Usuario](https://simplex.chat/docs/guide/app-settings.html#your-simplex-contact-address).</target> + <note>No comment provided by engineer.</note> + </trans-unit> + <trans-unit id="Read more in [User Guide](https://simplex.chat/docs/guide/chat-profiles.html#incognito-mode)." xml:space="preserve"> + <source>Read more in [User Guide](https://simplex.chat/docs/guide/chat-profiles.html#incognito-mode).</source> + <target>Saber más en [Guía de Usuario](https://simplex.chat/docs/guide/chat-profiles.html#incognito-mode).</target> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="Read more in [User Guide](https://simplex.chat/docs/guide/readme.html#connect-to-friends)." xml:space="preserve"> <source>Read more in [User Guide](https://simplex.chat/docs/guide/readme.html#connect-to-friends).</source> - <target>Más información en el [Manual de usuario](https://simplex.chat/docs/guide/readme.html#connect-to-friends).</target> + <target>Saber más en el [Manual del Usuario](https://simplex.chat/docs/guide/readme.html#connect-to-friends).</target> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="Read more in our GitHub repository." xml:space="preserve"> <source>Read more in our GitHub repository.</source> - <target>Más información en nuestro repositorio GitHub.</target> + <target>Saber más en nuestro repositorio GitHub.</target> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="Read more in our [GitHub repository](https://github.com/simplex-chat/simplex-chat#readme)." xml:space="preserve"> <source>Read more in our [GitHub repository](https://github.com/simplex-chat/simplex-chat#readme).</source> - <target>Más información en nuestro [repositorio GitHub](https://github.com/simplex-chat/simplex-chat#readme).</target> + <target>Saber más en nuestro [repositorio GitHub](https://github.com/simplex-chat/simplex-chat#readme).</target> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="Receipts are disabled" xml:space="preserve"> @@ -3991,6 +4192,10 @@ This is your link for group %@!</source> <target>Recibiendo vía</target> <note>No comment provided by engineer.</note> </trans-unit> + <trans-unit id="Recent history and improved [directory bot](simplex:/contact#/?v=1-4&smp=smp%3A%2F%2Fu2dS9sG8nMNURyZwqASV4yROM28Er0luVTx5X1CsMrU%3D%40smp4.simplex.im%2FeXSPwqTkKyDO3px4fLf1wx3MvPdjdLW3%23%2F%3Fv%3D1-2%26dh%3DMCowBQYDK2VuAyEAaiv6MkMH44L2TcYrt_CsX3ZvM11WgbMEUn0hkIKTOho%253D%26srv%3Do5vmywmrnaxalvz6wi3zicyftgio6psuvyniis6gco6bp6ekl4cqj4id.onion)." xml:space="preserve"> + <source>Recent history and improved [directory bot](simplex:/contact#/?v=1-4&smp=smp%3A%2F%2Fu2dS9sG8nMNURyZwqASV4yROM28Er0luVTx5X1CsMrU%3D%40smp4.simplex.im%2FeXSPwqTkKyDO3px4fLf1wx3MvPdjdLW3%23%2F%3Fv%3D1-2%26dh%3DMCowBQYDK2VuAyEAaiv6MkMH44L2TcYrt_CsX3ZvM11WgbMEUn0hkIKTOho%253D%26srv%3Do5vmywmrnaxalvz6wi3zicyftgio6psuvyniis6gco6bp6ekl4cqj4id.onion).</source> + <note>No comment provided by engineer.</note> + </trans-unit> <trans-unit id="Recipients see updates as you type them." xml:space="preserve"> <source>Recipients see updates as you type them.</source> <target>Los destinatarios ven actualizarse mientras escribes.</target> @@ -4083,10 +4288,12 @@ This is your link for group %@!</source> </trans-unit> <trans-unit id="Repeat connection request?" xml:space="preserve"> <source>Repeat connection request?</source> + <target>¿Repetir solicitud de conexión?</target> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="Repeat join request?" xml:space="preserve"> <source>Repeat join request?</source> + <target>¿Repetir solicitud de admisión?</target> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="Reply" xml:space="preserve"> @@ -4144,6 +4351,11 @@ This is your link for group %@!</source> <target>Error al restaurar base de datos</target> <note>No comment provided by engineer.</note> </trans-unit> + <trans-unit id="Retry" xml:space="preserve"> + <source>Retry</source> + <target>Reintentar</target> + <note>No comment provided by engineer.</note> + </trans-unit> <trans-unit id="Reveal" xml:space="preserve"> <source>Reveal</source> <target>Revelar</target> @@ -4201,12 +4413,12 @@ This is your link for group %@!</source> </trans-unit> <trans-unit id="Save and notify group members" xml:space="preserve"> <source>Save and notify group members</source> - <target>Guardar y notificar a los miembros del grupo</target> + <target>Guardar y notificar grupo</target> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="Save and update group profile" xml:space="preserve"> <source>Save and update group profile</source> - <target>Guardar y actualizar perfil de grupo</target> + <target>Guardar y actualizar perfil del grupo</target> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="Save archive" xml:space="preserve"> @@ -4269,6 +4481,10 @@ This is your link for group %@!</source> <target>Los servidores WebRTC ICE guardados serán eliminados</target> <note>No comment provided by engineer.</note> </trans-unit> + <trans-unit id="Saved message" xml:space="preserve"> + <source>Saved message</source> + <note>message info title</note> + </trans-unit> <trans-unit id="Scan QR code" xml:space="preserve"> <source>Scan QR code</source> <target>Escanear código QR</target> @@ -4276,6 +4492,7 @@ This is your link for group %@!</source> </trans-unit> <trans-unit id="Scan QR code from desktop" xml:space="preserve"> <source>Scan QR code from desktop</source> + <target>Escanear código QR desde ordenador</target> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="Scan code" xml:space="preserve"> @@ -4298,6 +4515,15 @@ This is your link for group %@!</source> <target>Buscar</target> <note>No comment provided by engineer.</note> </trans-unit> + <trans-unit id="Search bar accepts invitation links." xml:space="preserve"> + <source>Search bar accepts invitation links.</source> + <note>No comment provided by engineer.</note> + </trans-unit> + <trans-unit id="Search or paste SimpleX link" xml:space="preserve"> + <source>Search or paste SimpleX link</source> + <target>Buscar o pegar enlace SimpleX</target> + <note>No comment provided by engineer.</note> + </trans-unit> <trans-unit id="Secure queue" xml:space="preserve"> <source>Secure queue</source> <target>Cola segura</target> @@ -4403,6 +4629,10 @@ This is your link for group %@!</source> <target>Envíalos desde la galería o desde teclados personalizados.</target> <note>No comment provided by engineer.</note> </trans-unit> + <trans-unit id="Send up to 100 last messages to new members." xml:space="preserve"> + <source>Send up to 100 last messages to new members.</source> + <note>No comment provided by engineer.</note> + </trans-unit> <trans-unit id="Sender cancelled file transfer." xml:space="preserve"> <source>Sender cancelled file transfer.</source> <target>El remitente ha cancelado la transferencia de archivos.</target> @@ -4500,6 +4730,7 @@ This is your link for group %@!</source> </trans-unit> <trans-unit id="Session code" xml:space="preserve"> <source>Session code</source> + <target>Código de sesión</target> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="Set 1 day" xml:space="preserve"> @@ -4572,9 +4803,9 @@ This is your link for group %@!</source> <target>Compartir enlace</target> <note>No comment provided by engineer.</note> </trans-unit> - <trans-unit id="Share one-time invitation link" xml:space="preserve"> - <source>Share one-time invitation link</source> - <target>Compartir enlace de invitación de un uso</target> + <trans-unit id="Share this 1-time invite link" xml:space="preserve"> + <source>Share this 1-time invite link</source> + <target>Compartir este enlace de un uso</target> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="Share with contacts" xml:space="preserve"> @@ -4697,16 +4928,16 @@ This is your link for group %@!</source> <target>Alguien</target> <note>notification title</note> </trans-unit> - <trans-unit id="Start a new chat" xml:space="preserve"> - <source>Start a new chat</source> - <target>Iniciar chat nuevo</target> - <note>No comment provided by engineer.</note> - </trans-unit> <trans-unit id="Start chat" xml:space="preserve"> <source>Start chat</source> <target>Iniciar chat</target> <note>No comment provided by engineer.</note> </trans-unit> + <trans-unit id="Start chat?" xml:space="preserve"> + <source>Start chat?</source> + <target>¿Iniciar chat?</target> + <note>No comment provided by engineer.</note> + </trans-unit> <trans-unit id="Start migration" xml:space="preserve"> <source>Start migration</source> <target>Iniciar migración</target> @@ -4814,6 +5045,7 @@ This is your link for group %@!</source> </trans-unit> <trans-unit id="Tap to Connect" xml:space="preserve"> <source>Tap to Connect</source> + <target>Pulsa para conectar</target> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="Tap to activate profile." xml:space="preserve"> @@ -4823,7 +5055,7 @@ This is your link for group %@!</source> </trans-unit> <trans-unit id="Tap to join" xml:space="preserve"> <source>Tap to join</source> - <target>Pulsa para unirse</target> + <target>Pulsa para unirte</target> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="Tap to join incognito" xml:space="preserve"> @@ -4831,6 +5063,16 @@ This is your link for group %@!</source> <target>Pulsa para unirte en modo incógnito</target> <note>No comment provided by engineer.</note> </trans-unit> + <trans-unit id="Tap to paste link" xml:space="preserve"> + <source>Tap to paste link</source> + <target>Pulsa para pegar enlace</target> + <note>No comment provided by engineer.</note> + </trans-unit> + <trans-unit id="Tap to scan" xml:space="preserve"> + <source>Tap to scan</source> + <target>Pulsa para escanear</target> + <note>No comment provided by engineer.</note> + </trans-unit> <trans-unit id="Tap to start a new chat" xml:space="preserve"> <source>Tap to start a new chat</source> <target>Pulsa para iniciar chat nuevo</target> @@ -4893,6 +5135,11 @@ Puede ocurrir por algún bug o cuando la conexión está comprometida.</target> <target>El intento de cambiar la contraseña de la base de datos no se ha completado.</target> <note>No comment provided by engineer.</note> </trans-unit> + <trans-unit id="The code you scanned is not a SimpleX link QR code." xml:space="preserve"> + <source>The code you scanned is not a SimpleX link QR code.</source> + <target>El código QR escaneado no es un enlace SimpleX.</target> + <note>No comment provided by engineer.</note> + </trans-unit> <trans-unit id="The connection you accepted will be cancelled!" xml:space="preserve"> <source>The connection you accepted will be cancelled!</source> <target>¡La conexión que has aceptado se cancelará!</target> @@ -4958,21 +5205,16 @@ Puede ocurrir por algún bug o cuando la conexión está comprometida.</target> <target>Lista de servidores para las conexiones nuevas de tu perfil actual **%@**.</target> <note>No comment provided by engineer.</note> </trans-unit> + <trans-unit id="The text you pasted is not a SimpleX link." xml:space="preserve"> + <source>The text you pasted is not a SimpleX link.</source> + <target>El texto pegado no es un enlace SimpleX.</target> + <note>No comment provided by engineer.</note> + </trans-unit> <trans-unit id="Theme" xml:space="preserve"> <source>Theme</source> <target>Tema</target> <note>No comment provided by engineer.</note> </trans-unit> - <trans-unit id="There should be at least one user profile." xml:space="preserve"> - <source>There should be at least one user profile.</source> - <target>Debe haber al menos un perfil.</target> - <note>No comment provided by engineer.</note> - </trans-unit> - <trans-unit id="There should be at least one visible user profile." xml:space="preserve"> - <source>There should be at least one visible user profile.</source> - <target>Debe haber al menos un perfil visible.</target> - <note>No comment provided by engineer.</note> - </trans-unit> <trans-unit id="These settings are for your current profile **%@**." xml:space="preserve"> <source>These settings are for your current profile **%@**.</source> <target>Esta configuración afecta a tu perfil actual **%@**.</target> @@ -5000,6 +5242,11 @@ Puede ocurrir por algún bug o cuando la conexión está comprometida.</target> </trans-unit> <trans-unit id="This device name" xml:space="preserve"> <source>This device name</source> + <target>Nombre del dispositivo</target> + <note>No comment provided by engineer.</note> + </trans-unit> + <trans-unit id="This display name is invalid. Please choose another name." xml:space="preserve"> + <source>This display name is invalid. Please choose another name.</source> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="This group has over %lld members, delivery receipts are not sent." xml:space="preserve"> @@ -5014,10 +5261,12 @@ Puede ocurrir por algún bug o cuando la conexión está comprometida.</target> </trans-unit> <trans-unit id="This is your own SimpleX address!" xml:space="preserve"> <source>This is your own SimpleX address!</source> + <target>¡Esta es tu propia dirección SimpleX!</target> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="This is your own one-time link!" xml:space="preserve"> <source>This is your own one-time link!</source> + <target>¡Este es tu propio enlace de un solo uso!</target> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="This setting applies to messages in your current chat profile **%@**." xml:space="preserve"> @@ -5037,6 +5286,7 @@ Puede ocurrir por algún bug o cuando la conexión está comprometida.</target> </trans-unit> <trans-unit id="To hide unwanted messages." xml:space="preserve"> <source>To hide unwanted messages.</source> + <target>Para ocultar mensajes no deseados.</target> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="To make a new connection" xml:space="preserve"> @@ -5046,7 +5296,7 @@ Puede ocurrir por algún bug o cuando la conexión está comprometida.</target> </trans-unit> <trans-unit id="To protect privacy, instead of user IDs used by all other platforms, SimpleX has identifiers for message queues, separate for each of your contacts." xml:space="preserve"> <source>To protect privacy, instead of user IDs used by all other platforms, SimpleX has identifiers for message queues, separate for each of your contacts.</source> - <target>Para proteger la privacidad, en lugar de los identificadores de usuario que usan el resto de plataformas, SimpleX dispone de identificadores para las colas de mensajes, independientes para cada uno de tus contactos.</target> + <target>Para proteger tu privacidad, en lugar de los identificadores de usuario que usan el resto de plataformas, SimpleX dispone de identificadores para las colas de mensajes, independientes para cada uno de tus contactos.</target> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="To protect timezone, image/voice files use UTC." xml:space="preserve"> @@ -5057,7 +5307,7 @@ Puede ocurrir por algún bug o cuando la conexión está comprometida.</target> <trans-unit id="To protect your information, turn on SimpleX Lock. You will be prompted to complete authentication before this feature is enabled." xml:space="preserve"> <source>To protect your information, turn on SimpleX Lock. You will be prompted to complete authentication before this feature is enabled.</source> - <target>Para proteger tu información, activa Bloqueo SimpleX. + <target>Para proteger tu información, activa el Bloqueo SimpleX. Se te pedirá que completes la autenticación antes de activar esta función.</target> <note>No comment provided by engineer.</note> </trans-unit> @@ -5078,7 +5328,7 @@ Se te pedirá que completes la autenticación antes de activar esta función.</t </trans-unit> <trans-unit id="To verify end-to-end encryption with your contact compare (or scan) the code on your devices." xml:space="preserve"> <source>To verify end-to-end encryption with your contact compare (or scan) the code on your devices.</source> - <target>Para comprobar el cifrado de extremo a extremo con tu contacto compara (o escanea) el código en tus dispositivos.</target> + <target>Para verificar el cifrado de extremo a extremo con tu contacto, compara (o escanea) el código en ambos dispositivos.</target> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="Toggle incognito when connecting." xml:space="preserve"> @@ -5101,16 +5351,15 @@ Se te pedirá que completes la autenticación antes de activar esta función.</t <target>Intentando conectar con el servidor usado para recibir mensajes de este contacto.</target> <note>No comment provided by engineer.</note> </trans-unit> + <trans-unit id="Turkish interface" xml:space="preserve"> + <source>Turkish interface</source> + <note>No comment provided by engineer.</note> + </trans-unit> <trans-unit id="Turn off" xml:space="preserve"> <source>Turn off</source> <target>Desactivar</target> <note>No comment provided by engineer.</note> </trans-unit> - <trans-unit id="Turn off notifications?" xml:space="preserve"> - <source>Turn off notifications?</source> - <target>¿Desactivar notificaciones?</target> - <note>No comment provided by engineer.</note> - </trans-unit> <trans-unit id="Turn on" xml:space="preserve"> <source>Turn on</source> <target>Activar</target> @@ -5123,14 +5372,25 @@ Se te pedirá que completes la autenticación antes de activar esta función.</t </trans-unit> <trans-unit id="Unblock" xml:space="preserve"> <source>Unblock</source> + <target>Desbloquear</target> + <note>No comment provided by engineer.</note> + </trans-unit> + <trans-unit id="Unblock for all" xml:space="preserve"> + <source>Unblock for all</source> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="Unblock member" xml:space="preserve"> <source>Unblock member</source> + <target>Desbloquear miembro</target> + <note>No comment provided by engineer.</note> + </trans-unit> + <trans-unit id="Unblock member for all?" xml:space="preserve"> + <source>Unblock member for all?</source> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="Unblock member?" xml:space="preserve"> <source>Unblock member?</source> + <target>¿Desbloquear miembro?</target> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="Unexpected error: %@" xml:space="preserve"> @@ -5198,10 +5458,12 @@ Para conectarte, pide a tu contacto que cree otro enlace de conexión y comprueb </trans-unit> <trans-unit id="Unlink" xml:space="preserve"> <source>Unlink</source> + <target>Desenlazar</target> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="Unlink desktop?" xml:space="preserve"> <source>Unlink desktop?</source> + <target>¿Desenlazar ordenador?</target> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="Unlock" xml:space="preserve"> @@ -5224,6 +5486,10 @@ Para conectarte, pide a tu contacto que cree otro enlace de conexión y comprueb <target>No leído</target> <note>No comment provided by engineer.</note> </trans-unit> + <trans-unit id="Up to 100 last messages are sent to new members." xml:space="preserve"> + <source>Up to 100 last messages are sent to new members.</source> + <note>No comment provided by engineer.</note> + </trans-unit> <trans-unit id="Update" xml:space="preserve"> <source>Update</source> <target>Actualizar</target> @@ -5296,6 +5562,7 @@ Para conectarte, pide a tu contacto que cree otro enlace de conexión y comprueb </trans-unit> <trans-unit id="Use from desktop" xml:space="preserve"> <source>Use from desktop</source> + <target>Usar desde ordenador</target> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="Use iOS call interface" xml:space="preserve"> @@ -5308,6 +5575,11 @@ Para conectarte, pide a tu contacto que cree otro enlace de conexión y comprueb <target>Usar nuevo perfil incógnito</target> <note>No comment provided by engineer.</note> </trans-unit> + <trans-unit id="Use only local notifications?" xml:space="preserve"> + <source>Use only local notifications?</source> + <target>¿Usar sólo notificaciones locales?</target> + <note>No comment provided by engineer.</note> + </trans-unit> <trans-unit id="Use server" xml:space="preserve"> <source>Use server</source> <target>Usar servidor</target> @@ -5330,10 +5602,12 @@ Para conectarte, pide a tu contacto que cree otro enlace de conexión y comprueb </trans-unit> <trans-unit id="Verify code with desktop" xml:space="preserve"> <source>Verify code with desktop</source> + <target>Verificar código con ordenador</target> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="Verify connection" xml:space="preserve"> <source>Verify connection</source> + <target>Verificar conexión</target> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="Verify connection security" xml:space="preserve"> @@ -5343,6 +5617,7 @@ Para conectarte, pide a tu contacto que cree otro enlace de conexión y comprueb </trans-unit> <trans-unit id="Verify connections" xml:space="preserve"> <source>Verify connections</source> + <target>Verificar conexiones</target> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="Verify security code" xml:space="preserve"> @@ -5357,6 +5632,7 @@ Para conectarte, pide a tu contacto que cree otro enlace de conexión y comprueb </trans-unit> <trans-unit id="Via secure quantum resistant protocol." xml:space="preserve"> <source>Via secure quantum resistant protocol.</source> + <target>Mediante protocolo seguro de resistencia cuántica.</target> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="Video call" xml:space="preserve"> @@ -5384,6 +5660,10 @@ Para conectarte, pide a tu contacto que cree otro enlace de conexión y comprueb <target>Mostrar código de seguridad</target> <note>No comment provided by engineer.</note> </trans-unit> + <trans-unit id="Visible history" xml:space="preserve"> + <source>Visible history</source> + <note>chat feature</note> + </trans-unit> <trans-unit id="Voice messages" xml:space="preserve"> <source>Voice messages</source> <target>Mensajes de voz</target> @@ -5411,6 +5691,7 @@ Para conectarte, pide a tu contacto que cree otro enlace de conexión y comprueb </trans-unit> <trans-unit id="Waiting for desktop..." xml:space="preserve"> <source>Waiting for desktop...</source> + <target>Esperando ordenador...</target> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="Waiting for file" xml:space="preserve"> @@ -5468,11 +5749,19 @@ Para conectarte, pide a tu contacto que cree otro enlace de conexión y comprueb <target>Cuando compartes un perfil incógnito con alguien, este perfil también se usará para los grupos a los que te inviten.</target> <note>No comment provided by engineer.</note> </trans-unit> + <trans-unit id="With encrypted files and media." xml:space="preserve"> + <source>With encrypted files and media.</source> + <note>No comment provided by engineer.</note> + </trans-unit> <trans-unit id="With optional welcome message." xml:space="preserve"> <source>With optional welcome message.</source> <target>Con mensaje de bienvenida opcional.</target> <note>No comment provided by engineer.</note> </trans-unit> + <trans-unit id="With reduced battery usage." xml:space="preserve"> + <source>With reduced battery usage.</source> + <note>No comment provided by engineer.</note> + </trans-unit> <trans-unit id="Wrong database passphrase" xml:space="preserve"> <source>Wrong database passphrase</source> <target>Contraseña de base de datos incorrecta</target> @@ -5515,31 +5804,39 @@ Para conectarte, pide a tu contacto que cree otro enlace de conexión y comprueb </trans-unit> <trans-unit id="You are already connecting to %@." xml:space="preserve"> <source>You are already connecting to %@.</source> + <target>Ya estás conectando con %@.</target> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="You are already connecting via this one-time link!" xml:space="preserve"> <source>You are already connecting via this one-time link!</source> + <target>¡Ya estás conectando mediante este enlace de un solo uso!</target> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="You are already in group %@." xml:space="preserve"> <source>You are already in group %@.</source> + <target>Ya estás en el grupo %@.</target> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="You are already joining the group %@." xml:space="preserve"> <source>You are already joining the group %@.</source> + <target>Ya estás uniéndote al grupo %@.</target> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="You are already joining the group via this link!" xml:space="preserve"> <source>You are already joining the group via this link!</source> + <target>¡Ya estás uniéndote al grupo mediante este enlace!</target> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="You are already joining the group via this link." xml:space="preserve"> <source>You are already joining the group via this link.</source> + <target>Ya estás uniéndote al grupo mediante este enlace.</target> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="You are already joining the group! Repeat join request?" xml:space="preserve"> <source>You are already joining the group! Repeat join request?</source> + <target>¡En proceso de unirte al grupo! +¿Repetir solicitud de admisión?</target> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="You are connected to the server used to receive messages from this contact." xml:space="preserve"> @@ -5549,7 +5846,7 @@ Repeat join request?</source> </trans-unit> <trans-unit id="You are invited to group" xml:space="preserve"> <source>You are invited to group</source> - <target>Has sido invitado al grupo</target> + <target>Has sido invitado a un grupo</target> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="You can accept calls from lock screen, without device and app authentication." xml:space="preserve"> @@ -5557,11 +5854,6 @@ Repeat join request?</source> <target>Puede aceptar llamadas desde la pantalla de bloqueo, sin autenticación de dispositivos y aplicaciones.</target> <note>No comment provided by engineer.</note> </trans-unit> - <trans-unit id="You can also connect by clicking the link. If it opens in the browser, click **Open in mobile app** button." xml:space="preserve"> - <source>You can also connect by clicking the link. If it opens in the browser, click **Open in mobile app** button.</source> - <target>También puedes conectarte haciendo clic en el enlace. Si se abre en el navegador, haz clic en el botón **Abrir en aplicación móvil**.</target> - <note>No comment provided by engineer.</note> - </trans-unit> <trans-unit id="You can create it later" xml:space="preserve"> <source>You can create it later</source> <target>Puedes crearla más tarde</target> @@ -5582,6 +5874,11 @@ Repeat join request?</source> <target>Puedes ocultar o silenciar un perfil deslizándolo a la derecha.</target> <note>No comment provided by engineer.</note> </trans-unit> + <trans-unit id="You can make it visible to your SimpleX contacts via Settings." xml:space="preserve"> + <source>You can make it visible to your SimpleX contacts via Settings.</source> + <target>Puedes hacerlo visible para tus contactos de SimpleX en Configuración.</target> + <note>No comment provided by engineer.</note> + </trans-unit> <trans-unit id="You can now send messages to %@" xml:space="preserve"> <source>You can now send messages to %@</source> <target>Ya puedes enviar mensajes a %@</target> @@ -5594,7 +5891,7 @@ Repeat join request?</source> </trans-unit> <trans-unit id="You can share a link or a QR code - anybody will be able to join the group. You won't lose members of the group if you later delete it." xml:space="preserve"> <source>You can share a link or a QR code - anybody will be able to join the group. You won't lose members of the group if you later delete it.</source> - <target>Puedes compartir un enlace o un código QR: cualquiera podrá unirse al grupo. Si lo eliminas más tarde los miembros del grupo no se perderán.</target> + <target>Puedes compartir un enlace o código QR para que cualquiera pueda unirse al grupo. Si decides eliminarlo más tarde, los miembros del grupo se mantendrán.</target> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="You can share this address with your contacts to let them connect with **%@**." xml:space="preserve"> @@ -5604,7 +5901,7 @@ Repeat join request?</source> </trans-unit> <trans-unit id="You can share your address as a link or QR code - anybody can connect to you." xml:space="preserve"> <source>You can share your address as a link or QR code - anybody can connect to you.</source> - <target>Puedes compartir tu dirección como enlace o como código QR: cualquiera podrá conectarse contigo.</target> + <target>Puedes compartir tu dirección como enlace o código QR para que cualquiera pueda conectarse contigo.</target> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="You can start chat via app Settings / Database or by restarting the app" xml:space="preserve"> @@ -5622,6 +5919,11 @@ Repeat join request?</source> <target>Puedes usar la sintaxis markdown para dar formato a tus mensajes:</target> <note>No comment provided by engineer.</note> </trans-unit> + <trans-unit id="You can view invitation link again in connection details." xml:space="preserve"> + <source>You can view invitation link again in connection details.</source> + <target>Podrás ver el enlace de invitación en detalles de conexión.</target> + <note>No comment provided by engineer.</note> + </trans-unit> <trans-unit id="You can't send messages!" xml:space="preserve"> <source>You can't send messages!</source> <target>¡No puedes enviar mensajes!</target> @@ -5639,11 +5941,14 @@ Repeat join request?</source> </trans-unit> <trans-unit id="You have already requested connection via this address!" xml:space="preserve"> <source>You have already requested connection via this address!</source> + <target>¡Ya has solicitado la conexión mediante esta dirección!</target> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="You have already requested connection! Repeat connection request?" xml:space="preserve"> <source>You have already requested connection! Repeat connection request?</source> + <target>Ya has solicitado la conexión +¿Repetir solicitud?</target> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="You have no chats" xml:space="preserve"> @@ -5698,6 +6003,7 @@ Repeat connection request?</source> </trans-unit> <trans-unit id="You will be connected when group link host's device is online, please wait or check later!" xml:space="preserve"> <source>You will be connected when group link host's device is online, please wait or check later!</source> + <target>Te conectarás cuando el dispositivo propietario del grupo esté en línea, por favor espera o compruébalo más tarde.</target> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="You will be connected when your connection request is accepted, please wait or check later!" xml:space="preserve"> @@ -5717,6 +6023,7 @@ Repeat connection request?</source> </trans-unit> <trans-unit id="You will connect to all group members." xml:space="preserve"> <source>You will connect to all group members.</source> + <target>Te conectarás con todos los miembros del grupo.</target> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="You will still receive calls and notifications from muted profiles when they are active." xml:space="preserve"> @@ -5741,7 +6048,7 @@ Repeat connection request?</source> </trans-unit> <trans-unit id="You're using an incognito profile for this group - to prevent sharing your main profile inviting contacts is not allowed" xml:space="preserve"> <source>You're using an incognito profile for this group - to prevent sharing your main profile inviting contacts is not allowed</source> - <target>Estás usando un perfil incógnito para este grupo, por tanto para evitar compartir tu perfil principal no se permite invitar a contactos</target> + <target>Estás usando un perfil incógnito en este grupo. Para evitar descubrir tu perfil principal no se permite invitar contactos</target> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="Your %@ servers" xml:space="preserve"> @@ -5806,13 +6113,6 @@ Puedes cancelar esta conexión y eliminar el contacto (e intentarlo más tarde c <target>Tus contactos pueden permitir la eliminación completa de mensajes.</target> <note>No comment provided by engineer.</note> </trans-unit> - <trans-unit id="Your contacts in SimpleX will see it. You can change it in Settings." xml:space="preserve"> - <source>Your contacts in SimpleX will see it. -You can change it in Settings.</source> - <target>Tus contactos en SimpleX lo verán. -Puedes cambiarlo en Configuración.</target> - <note>No comment provided by engineer.</note> - </trans-unit> <trans-unit id="Your contacts will remain connected." xml:space="preserve"> <source>Your contacts will remain connected.</source> <target>Tus contactos permanecerán conectados.</target> @@ -5840,6 +6140,7 @@ Puedes cambiarlo en Configuración.</target> </trans-unit> <trans-unit id="Your profile" xml:space="preserve"> <source>Your profile</source> + <target>Tu perfil</target> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="Your profile **%@** will be shared." xml:space="preserve"> @@ -5936,6 +6237,7 @@ Los servidores de SimpleX no pueden ver tu perfil.</target> </trans-unit> <trans-unit id="and %lld other events" xml:space="preserve"> <source>and %lld other events</source> + <target>y %lld evento(s) más</target> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="audio call (not e2e encrypted)" xml:space="preserve"> @@ -5945,6 +6247,7 @@ Los servidores de SimpleX no pueden ver tu perfil.</target> </trans-unit> <trans-unit id="author" xml:space="preserve"> <source>author</source> + <target>autor</target> <note>member role</note> </trans-unit> <trans-unit id="bad message ID" xml:space="preserve"> @@ -5959,8 +6262,17 @@ Los servidores de SimpleX no pueden ver tu perfil.</target> </trans-unit> <trans-unit id="blocked" xml:space="preserve"> <source>blocked</source> + <target>bloqueado</target> <note>No comment provided by engineer.</note> </trans-unit> + <trans-unit id="blocked %@" xml:space="preserve"> + <source>blocked %@</source> + <note>rcv group event chat item</note> + </trans-unit> + <trans-unit id="blocked by admin" xml:space="preserve"> + <source>blocked by admin</source> + <note>blocked chat item</note> + </trans-unit> <trans-unit id="bold" xml:space="preserve"> <source>bold</source> <target>negrita</target> @@ -5988,7 +6300,7 @@ Los servidores de SimpleX no pueden ver tu perfil.</target> </trans-unit> <trans-unit id="changed address for you" xml:space="preserve"> <source>changed address for you</source> - <target>el servidor de envío ha cambiado para tí</target> + <target>ha cambiado tu servidor de envío</target> <note>chat item text</note> </trans-unit> <trans-unit id="changed role of %@ to %@" xml:space="preserve"> @@ -6003,12 +6315,12 @@ Los servidores de SimpleX no pueden ver tu perfil.</target> </trans-unit> <trans-unit id="changing address for %@…" xml:space="preserve"> <source>changing address for %@…</source> - <target>cambiando dirección para %@…</target> + <target>cambiando el servidor para %@…</target> <note>chat item text</note> </trans-unit> <trans-unit id="changing address…" xml:space="preserve"> <source>changing address…</source> - <target>cambiando dirección…</target> + <target>cambiando de servidor…</target> <note>chat item text</note> </trans-unit> <trans-unit id="colored" xml:space="preserve"> @@ -6081,6 +6393,10 @@ Los servidores de SimpleX no pueden ver tu perfil.</target> <target>conexión: % @</target> <note>connection information</note> </trans-unit> + <trans-unit id="contact %@ changed to %@" xml:space="preserve"> + <source>contact %1$@ changed to %2$@</source> + <note>profile update event chat item</note> + </trans-unit> <trans-unit id="contact has e2e encryption" xml:space="preserve"> <source>contact has e2e encryption</source> <target>el contacto dispone de cifrado de extremo a extremo</target> @@ -6133,6 +6449,7 @@ Los servidores de SimpleX no pueden ver tu perfil.</target> </trans-unit> <trans-unit id="deleted contact" xml:space="preserve"> <source>deleted contact</source> + <target>contacto eliminado</target> <note>rcv direct event chat item</note> </trans-unit> <trans-unit id="deleted group" xml:space="preserve"> @@ -6317,7 +6634,7 @@ Los servidores de SimpleX no pueden ver tu perfil.</target> </trans-unit> <trans-unit id="invited to connect" xml:space="preserve"> <source>invited to connect</source> - <target>invitado a conectarse</target> + <target>invitación a conectarse</target> <note>chat list item title</note> </trans-unit> <trans-unit id="invited via your group link" xml:space="preserve"> @@ -6350,6 +6667,10 @@ Los servidores de SimpleX no pueden ver tu perfil.</target> <target>miembro</target> <note>member role</note> </trans-unit> + <trans-unit id="member %@ changed to %@" xml:space="preserve"> + <source>member %1$@ changed to %2$@</source> + <note>profile update event chat item</note> + </trans-unit> <trans-unit id="member connected" xml:space="preserve"> <source>connected</source> <target>conectado</target> @@ -6472,6 +6793,14 @@ Los servidores de SimpleX no pueden ver tu perfil.</target> <target>ha expulsado a %@</target> <note>rcv group event chat item</note> </trans-unit> + <trans-unit id="removed contact address" xml:space="preserve"> + <source>removed contact address</source> + <note>profile update event chat item</note> + </trans-unit> + <trans-unit id="removed profile picture" xml:space="preserve"> + <source>removed profile picture</source> + <note>profile update event chat item</note> + </trans-unit> <trans-unit id="removed you" xml:space="preserve"> <source>removed you</source> <target>te ha expulsado</target> @@ -6502,6 +6831,14 @@ Los servidores de SimpleX no pueden ver tu perfil.</target> <target>Enviar mensaje directo</target> <note>No comment provided by engineer.</note> </trans-unit> + <trans-unit id="set new contact address" xml:space="preserve"> + <source>set new contact address</source> + <note>profile update event chat item</note> + </trans-unit> + <trans-unit id="set new profile picture" xml:space="preserve"> + <source>set new profile picture</source> + <note>profile update event chat item</note> + </trans-unit> <trans-unit id="starting…" xml:space="preserve"> <source>starting…</source> <target>inicializando…</target> @@ -6517,18 +6854,31 @@ Los servidores de SimpleX no pueden ver tu perfil.</target> <target>este contacto</target> <note>notification title</note> </trans-unit> + <trans-unit id="unblocked %@" xml:space="preserve"> + <source>unblocked %@</source> + <note>rcv group event chat item</note> + </trans-unit> <trans-unit id="unknown" xml:space="preserve"> <source>unknown</source> <target>desconocido</target> <note>connection info</note> </trans-unit> + <trans-unit id="unknown status" xml:space="preserve"> + <source>unknown status</source> + <note>No comment provided by engineer.</note> + </trans-unit> <trans-unit id="updated group profile" xml:space="preserve"> <source>updated group profile</source> <target>ha actualizado el perfil del grupo</target> <note>rcv group event chat item</note> </trans-unit> + <trans-unit id="updated profile" xml:space="preserve"> + <source>updated profile</source> + <note>profile update event chat item</note> + </trans-unit> <trans-unit id="v%@" xml:space="preserve"> <source>v%@</source> + <target>v%@</target> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="v%@ (%@)" xml:space="preserve"> @@ -6588,7 +6938,7 @@ Los servidores de SimpleX no pueden ver tu perfil.</target> </trans-unit> <trans-unit id="you are invited to group" xml:space="preserve"> <source>you are invited to group</source> - <target>has sido invitado al grupo</target> + <target>has sido invitado a un grupo</target> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="you are observer" xml:space="preserve"> @@ -6596,6 +6946,10 @@ Los servidores de SimpleX no pueden ver tu perfil.</target> <target>Tu rol es observador</target> <note>No comment provided by engineer.</note> </trans-unit> + <trans-unit id="you blocked %@" xml:space="preserve"> + <source>you blocked %@</source> + <note>snd group event chat item</note> + </trans-unit> <trans-unit id="you changed address" xml:space="preserve"> <source>you changed address</source> <target>has cambiado de servidor</target> @@ -6628,7 +6982,7 @@ Los servidores de SimpleX no pueden ver tu perfil.</target> </trans-unit> <trans-unit id="you shared one-time link" xml:space="preserve"> <source>you shared one-time link</source> - <target>has compartido un enlace de un uso</target> + <target>enlace de un solo uso</target> <note>chat list item description</note> </trans-unit> <trans-unit id="you shared one-time link incognito" xml:space="preserve"> @@ -6636,6 +6990,10 @@ Los servidores de SimpleX no pueden ver tu perfil.</target> <target>has compartido enlace de un solo uso en modo incógnito</target> <note>chat list item description</note> </trans-unit> + <trans-unit id="you unblocked %@" xml:space="preserve"> + <source>you unblocked %@</source> + <note>snd group event chat item</note> + </trans-unit> <trans-unit id="you: " xml:space="preserve"> <source>you: </source> <target>tú: </target> @@ -6670,6 +7028,7 @@ Los servidores de SimpleX no pueden ver tu perfil.</target> </trans-unit> <trans-unit id="NSLocalNetworkUsageDescription" xml:space="preserve"> <source>SimpleX uses local network access to allow using user chat profile via desktop app on the same network.</source> + <target>SimpleX utiliza el acceso a la red local para abrir el perfil de chat en la aplicación de ordenador en la misma red.</target> <note>Privacy - Local Network Usage Description</note> </trans-unit> <trans-unit id="NSMicrophoneUsageDescription" xml:space="preserve"> diff --git a/apps/ios/SimpleX Localizations/fi.xcloc/Localized Contents/fi.xliff b/apps/ios/SimpleX Localizations/fi.xcloc/Localized Contents/fi.xliff index cf161efae4..91dd46fd09 100644 --- a/apps/ios/SimpleX Localizations/fi.xcloc/Localized Contents/fi.xliff +++ b/apps/ios/SimpleX Localizations/fi.xcloc/Localized Contents/fi.xliff @@ -212,6 +212,10 @@ <source>%lld messages blocked</source> <note>No comment provided by engineer.</note> </trans-unit> + <trans-unit id="%lld messages blocked by admin" xml:space="preserve"> + <source>%lld messages blocked by admin</source> + <note>No comment provided by engineer.</note> + </trans-unit> <trans-unit id="%lld messages marked deleted" xml:space="preserve"> <source>%lld messages marked deleted</source> <note>No comment provided by engineer.</note> @@ -303,14 +307,17 @@ <target>)</target> <note>No comment provided by engineer.</note> </trans-unit> + <trans-unit id="**Add contact**: to create a new invitation link, or connect via a link you received." xml:space="preserve"> + <source>**Add contact**: to create a new invitation link, or connect via a link you received.</source> + <note>No comment provided by engineer.</note> + </trans-unit> <trans-unit id="**Add new contact**: to create your one-time QR Code for your contact." xml:space="preserve"> <source>**Add new contact**: to create your one-time QR Code or link for your contact.</source> <target>**Lisää uusi kontakti**: luo kertakäyttöinen QR-koodi tai linkki kontaktille.</target> <note>No comment provided by engineer.</note> </trans-unit> - <trans-unit id="**Create link / QR code** for your contact to use." xml:space="preserve"> - <source>**Create link / QR code** for your contact to use.</source> - <target>**Luo linkki / QR-koodi* kontaktille.</target> + <trans-unit id="**Create group**: to create a new group." xml:space="preserve"> + <source>**Create group**: to create a new group.</source> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="**More private**: check new messages every 20 minutes. Device token is shared with SimpleX Chat server, but not how many contacts or messages you have." xml:space="preserve"> @@ -323,11 +330,6 @@ <target>**Yksityisin**: älä käytä SimpleX Chat -ilmoituspalvelinta, tarkista viestit ajoittain taustalla (riippuu siitä, kuinka usein käytät sovellusta).</target> <note>No comment provided by engineer.</note> </trans-unit> - <trans-unit id="**Paste received link** or open it in the browser and tap **Open in mobile app**." xml:space="preserve"> - <source>**Paste received link** or open it in the browser and tap **Open in mobile app**.</source> - <target>**Liitä vastaanotettu linkki** tai avaa se selaimessa ja napauta **Avaa mobiilisovelluksessa**.</target> - <note>No comment provided by engineer.</note> - </trans-unit> <trans-unit id="**Please note**: you will NOT be able to recover or change passphrase if you lose it." xml:space="preserve"> <source>**Please note**: you will NOT be able to recover or change passphrase if you lose it.</source> <target>**Huomaa**: et voi palauttaa tai muuttaa tunnuslausetta, jos kadotat sen.</target> @@ -338,11 +340,6 @@ <target>**Suositus**: laitetunnus ja ilmoitukset lähetetään SimpleX Chat -ilmoituspalvelimelle, mutta ei viestin sisältöä, kokoa tai sitä, keneltä se on peräisin.</target> <note>No comment provided by engineer.</note> </trans-unit> - <trans-unit id="**Scan QR code**: to connect to your contact in person or via video call." xml:space="preserve"> - <source>**Scan QR code**: to connect to your contact in person or via video call.</source> - <target>**Skannaa QR-koodi**: muodosta yhteys kontaktiisi henkilökohtaisesti tai videopuhelun kautta.</target> - <note>No comment provided by engineer.</note> - </trans-unit> <trans-unit id="**Warning**: Instant push notifications require passphrase saved in Keychain." xml:space="preserve"> <source>**Warning**: Instant push notifications require passphrase saved in Keychain.</source> <target>**Varoitus**: Välittömät push-ilmoitukset vaativat tunnuslauseen, joka on tallennettu Keychainiin.</target> @@ -437,11 +434,6 @@ <target>1 viikko</target> <note>time interval</note> </trans-unit> - <trans-unit id="1-time link" xml:space="preserve"> - <source>1-time link</source> - <target>Kertakäyttölinkki</target> - <note>No comment provided by engineer.</note> - </trans-unit> <trans-unit id="5 minutes" xml:space="preserve"> <source>5 minutes</source> <target>5 minuuttia</target> @@ -557,6 +549,10 @@ <target>Lisää osoite profiiliisi, jotta kontaktisi voivat jakaa sen muiden kanssa. Profiilipäivitys lähetetään kontakteillesi.</target> <note>No comment provided by engineer.</note> </trans-unit> + <trans-unit id="Add contact" xml:space="preserve"> + <source>Add contact</source> + <note>No comment provided by engineer.</note> + </trans-unit> <trans-unit id="Add preset servers" xml:space="preserve"> <source>Add preset servers</source> <target>Lisää esiasetettuja palvelimia</target> @@ -627,6 +623,10 @@ <target>Kaikki ryhmän jäsenet pysyvät yhteydessä.</target> <note>No comment provided by engineer.</note> </trans-unit> + <trans-unit id="All messages will be deleted - this cannot be undone!" xml:space="preserve"> + <source>All messages will be deleted - this cannot be undone!</source> + <note>No comment provided by engineer.</note> + </trans-unit> <trans-unit id="All messages will be deleted - this cannot be undone! The messages will be deleted ONLY for you." xml:space="preserve"> <source>All messages will be deleted - this cannot be undone! The messages will be deleted ONLY for you.</source> <target>Kaikki viestit poistetaan - tätä ei voi kumota! Viestit poistuvat VAIN sinulta.</target> @@ -661,9 +661,9 @@ <target>Salli katoavat viestit vain, jos kontaktisi sallii sen sinulle.</target> <note>No comment provided by engineer.</note> </trans-unit> - <trans-unit id="Allow irreversible message deletion only if your contact allows it to you." xml:space="preserve"> - <source>Allow irreversible message deletion only if your contact allows it to you.</source> - <target>Salli peruuttamaton viestien poisto vain, jos kontaktisi sallii ne sinulle.</target> + <trans-unit id="Allow irreversible message deletion only if your contact allows it to you. (24 hours)" xml:space="preserve"> + <source>Allow irreversible message deletion only if your contact allows it to you. (24 hours)</source> + <target>Salli peruuttamaton viestien poisto vain, jos kontaktisi sallii ne sinulle. (24 tuntia)</target> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="Allow message reactions only if your contact allows them." xml:space="preserve"> @@ -686,9 +686,9 @@ <target>Salli katoavien viestien lähettäminen.</target> <note>No comment provided by engineer.</note> </trans-unit> - <trans-unit id="Allow to irreversibly delete sent messages." xml:space="preserve"> - <source>Allow to irreversibly delete sent messages.</source> - <target>Salli lähetettyjen viestien peruuttamaton poistaminen.</target> + <trans-unit id="Allow to irreversibly delete sent messages. (24 hours)" xml:space="preserve"> + <source>Allow to irreversibly delete sent messages. (24 hours)</source> + <target>Salli lähetettyjen viestien peruuttamaton poistaminen. (24 tuntia)</target> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="Allow to send files and media." xml:space="preserve"> @@ -721,9 +721,9 @@ <target>Salli kontaktiesi soittaa sinulle.</target> <note>No comment provided by engineer.</note> </trans-unit> - <trans-unit id="Allow your contacts to irreversibly delete sent messages." xml:space="preserve"> - <source>Allow your contacts to irreversibly delete sent messages.</source> - <target>Salli kontaktiesi poistaa lähetetyt viestit peruuttamattomasti.</target> + <trans-unit id="Allow your contacts to irreversibly delete sent messages. (24 hours)" xml:space="preserve"> + <source>Allow your contacts to irreversibly delete sent messages. (24 hours)</source> + <target>Salli kontaktiesi poistaa lähetetyt viestit peruuttamattomasti. (24 tuntia)</target> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="Allow your contacts to send disappearing messages." xml:space="preserve"> @@ -895,6 +895,10 @@ <source>Block</source> <note>No comment provided by engineer.</note> </trans-unit> + <trans-unit id="Block for all" xml:space="preserve"> + <source>Block for all</source> + <note>No comment provided by engineer.</note> + </trans-unit> <trans-unit id="Block group members" xml:space="preserve"> <source>Block group members</source> <note>No comment provided by engineer.</note> @@ -903,18 +907,26 @@ <source>Block member</source> <note>No comment provided by engineer.</note> </trans-unit> + <trans-unit id="Block member for all?" xml:space="preserve"> + <source>Block member for all?</source> + <note>No comment provided by engineer.</note> + </trans-unit> <trans-unit id="Block member?" xml:space="preserve"> <source>Block member?</source> <note>No comment provided by engineer.</note> </trans-unit> + <trans-unit id="Blocked by admin" xml:space="preserve"> + <source>Blocked by admin</source> + <note>No comment provided by engineer.</note> + </trans-unit> <trans-unit id="Both you and your contact can add message reactions." xml:space="preserve"> <source>Both you and your contact can add message reactions.</source> <target>Sekä sinä että kontaktisi voivat käyttää viestireaktioita.</target> <note>No comment provided by engineer.</note> </trans-unit> - <trans-unit id="Both you and your contact can irreversibly delete sent messages." xml:space="preserve"> - <source>Both you and your contact can irreversibly delete sent messages.</source> - <target>Sekä sinä että kontaktisi voitte peruuttamattomasti poistaa lähetetyt viestit.</target> + <trans-unit id="Both you and your contact can irreversibly delete sent messages. (24 hours)" xml:space="preserve"> + <source>Both you and your contact can irreversibly delete sent messages. (24 hours)</source> + <target>Sekä sinä että kontaktisi voitte peruuttamattomasti poistaa lähetetyt viestit. (24 tuntia)</target> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="Both you and your contact can make calls." xml:space="preserve"> @@ -951,9 +963,8 @@ <target>Puhelut</target> <note>No comment provided by engineer.</note> </trans-unit> - <trans-unit id="Can't delete user profile!" xml:space="preserve"> - <source>Can't delete user profile!</source> - <target>Käyttäjäprofiilia ei voi poistaa!</target> + <trans-unit id="Camera not available" xml:space="preserve"> + <source>Camera not available</source> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="Can't invite contact!" xml:space="preserve"> @@ -1067,6 +1078,10 @@ <target>Chat on pysäytetty</target> <note>No comment provided by engineer.</note> </trans-unit> + <trans-unit id="Chat is stopped. If you already used this database on another device, you should transfer it back before starting chat." xml:space="preserve"> + <source>Chat is stopped. If you already used this database on another device, you should transfer it back before starting chat.</source> + <note>No comment provided by engineer.</note> + </trans-unit> <trans-unit id="Chat preferences" xml:space="preserve"> <source>Chat preferences</source> <target>Chat-asetukset</target> @@ -1112,6 +1127,10 @@ <target>Tyhjennä keskustelu?</target> <note>No comment provided by engineer.</note> </trans-unit> + <trans-unit id="Clear private notes?" xml:space="preserve"> + <source>Clear private notes?</source> + <note>No comment provided by engineer.</note> + </trans-unit> <trans-unit id="Clear verification" xml:space="preserve"> <source>Clear verification</source> <target>Tyhjennä vahvistus</target> @@ -1203,11 +1222,6 @@ This is your own one-time link!</source> <target>Yhdistä linkin kautta</target> <note>No comment provided by engineer.</note> </trans-unit> - <trans-unit id="Connect via link / QR code" xml:space="preserve"> - <source>Connect via link / QR code</source> - <target>Yhdistä linkillä / QR-koodilla</target> - <note>No comment provided by engineer.</note> - </trans-unit> <trans-unit id="Connect via one-time link" xml:space="preserve"> <source>Connect via one-time link</source> <target>Yhdistä kertalinkillä</target> @@ -1375,11 +1389,6 @@ This is your own one-time link!</source> <target>Luo uusi profiili [työpöytäsovelluksessa](https://simplex.chat/downloads/). 💻</target> <note>No comment provided by engineer.</note> </trans-unit> - <trans-unit id="Create one-time invitation link" xml:space="preserve"> - <source>Create one-time invitation link</source> - <target>Luo kertakutsulinkki</target> - <note>No comment provided by engineer.</note> - </trans-unit> <trans-unit id="Create profile" xml:space="preserve"> <source>Create profile</source> <note>No comment provided by engineer.</note> @@ -1399,11 +1408,23 @@ This is your own one-time link!</source> <target>Luo profiilisi</target> <note>No comment provided by engineer.</note> </trans-unit> + <trans-unit id="Created at" xml:space="preserve"> + <source>Created at</source> + <note>No comment provided by engineer.</note> + </trans-unit> + <trans-unit id="Created at: %@" xml:space="preserve"> + <source>Created at: %@</source> + <note>copied message info</note> + </trans-unit> <trans-unit id="Created on %@" xml:space="preserve"> <source>Created on %@</source> <target>Luotu %@</target> <note>No comment provided by engineer.</note> </trans-unit> + <trans-unit id="Creating link…" xml:space="preserve"> + <source>Creating link…</source> + <note>No comment provided by engineer.</note> + </trans-unit> <trans-unit id="Current Passcode" xml:space="preserve"> <source>Current Passcode</source> <target>Nykyinen pääsykoodi</target> @@ -1875,6 +1896,10 @@ This cannot be undone!</source> <target>Tee myöhemmin</target> <note>No comment provided by engineer.</note> </trans-unit> + <trans-unit id="Do not send history to new members." xml:space="preserve"> + <source>Do not send history to new members.</source> + <note>No comment provided by engineer.</note> + </trans-unit> <trans-unit id="Don't create address" xml:space="preserve"> <source>Don't create address</source> <target>Älä luo osoitetta</target> @@ -1945,6 +1970,10 @@ This cannot be undone!</source> <target>Ota automaattinen viestien poisto käyttöön?</target> <note>No comment provided by engineer.</note> </trans-unit> + <trans-unit id="Enable camera access" xml:space="preserve"> + <source>Enable camera access</source> + <note>No comment provided by engineer.</note> + </trans-unit> <trans-unit id="Enable for all" xml:space="preserve"> <source>Enable for all</source> <target>Salli kaikille</target> @@ -2009,6 +2038,10 @@ This cannot be undone!</source> <target>Salattu viesti tai muu tapahtuma</target> <note>notification</note> </trans-unit> + <trans-unit id="Encrypted message: app is stopped" xml:space="preserve"> + <source>Encrypted message: app is stopped</source> + <note>notification</note> + </trans-unit> <trans-unit id="Encrypted message: database error" xml:space="preserve"> <source>Encrypted message: database error</source> <target>Salattu viesti: tietokantavirhe</target> @@ -2148,6 +2181,10 @@ This cannot be undone!</source> <source>Error creating member contact</source> <note>No comment provided by engineer.</note> </trans-unit> + <trans-unit id="Error creating message" xml:space="preserve"> + <source>Error creating message</source> + <note>No comment provided by engineer.</note> + </trans-unit> <trans-unit id="Error creating profile!" xml:space="preserve"> <source>Error creating profile!</source> <target>Virhe profiilin luomisessa!</target> @@ -2233,6 +2270,10 @@ This cannot be undone!</source> <target>Virhe %@-palvelimien lataamisessa</target> <note>No comment provided by engineer.</note> </trans-unit> + <trans-unit id="Error opening chat" xml:space="preserve"> + <source>Error opening chat</source> + <note>No comment provided by engineer.</note> + </trans-unit> <trans-unit id="Error receiving file" xml:space="preserve"> <source>Error receiving file</source> <target>Virhe tiedoston vastaanottamisessa</target> @@ -2273,6 +2314,10 @@ This cannot be undone!</source> <target>Virhe käyttäjän salasanan tallentamisessa</target> <note>No comment provided by engineer.</note> </trans-unit> + <trans-unit id="Error scanning code: %@" xml:space="preserve"> + <source>Error scanning code: %@</source> + <note>No comment provided by engineer.</note> + </trans-unit> <trans-unit id="Error sending email" xml:space="preserve"> <source>Error sending email</source> <target>Virhe sähköpostin lähettämisessä</target> @@ -2596,9 +2641,9 @@ This cannot be undone!</source> <target>Ryhmän jäsenet voivat lisätä viestireaktioita.</target> <note>No comment provided by engineer.</note> </trans-unit> - <trans-unit id="Group members can irreversibly delete sent messages." xml:space="preserve"> - <source>Group members can irreversibly delete sent messages.</source> - <target>Ryhmän jäsenet voivat poistaa lähetetyt viestit peruuttamattomasti.</target> + <trans-unit id="Group members can irreversibly delete sent messages. (24 hours)" xml:space="preserve"> + <source>Group members can irreversibly delete sent messages. (24 hours)</source> + <target>Ryhmän jäsenet voivat poistaa lähetetyt viestit peruuttamattomasti. (24 tuntia)</target> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="Group members can send direct messages." xml:space="preserve"> @@ -2706,6 +2751,10 @@ This cannot be undone!</source> <target>Historia</target> <note>No comment provided by engineer.</note> </trans-unit> + <trans-unit id="History is not sent to new members." xml:space="preserve"> + <source>History is not sent to new members.</source> + <note>No comment provided by engineer.</note> + </trans-unit> <trans-unit id="How SimpleX works" xml:space="preserve"> <source>How SimpleX works</source> <target>Miten SimpleX toimii</target> @@ -2741,11 +2790,6 @@ This cannot be undone!</source> <target>Jos et voi tavata henkilökohtaisesti, näytä QR-koodi videopuhelussa tai jaa linkki.</target> <note>No comment provided by engineer.</note> </trans-unit> - <trans-unit id="If you cannot meet in person, you can **scan QR code in the video call**, or your contact can share an invitation link." xml:space="preserve"> - <source>If you cannot meet in person, you can **scan QR code in the video call**, or your contact can share an invitation link.</source> - <target>Jos et voi tavata henkilökohtaisesti, voit **skannata QR-koodin videopuhelussa** tai kontaktisi voi jakaa kutsulinkin.</target> - <note>No comment provided by engineer.</note> - </trans-unit> <trans-unit id="If you enter this passcode when opening the app, all app data will be irreversibly removed!" xml:space="preserve"> <source>If you enter this passcode when opening the app, all app data will be irreversibly removed!</source> <target>Jos syötät tämän pääsykoodin sovellusta avatessasi, kaikki sovelluksen tiedot poistetaan peruuttamattomasti!</target> @@ -2801,6 +2845,10 @@ This cannot be undone!</source> <target>Tuo tietokanta</target> <note>No comment provided by engineer.</note> </trans-unit> + <trans-unit id="Improved message delivery" xml:space="preserve"> + <source>Improved message delivery</source> + <note>No comment provided by engineer.</note> + </trans-unit> <trans-unit id="Improved privacy and security" xml:space="preserve"> <source>Improved privacy and security</source> <target>Parannettu yksityisyys ja turvallisuus</target> @@ -2901,15 +2949,31 @@ This cannot be undone!</source> <target>Käyttöliittymä</target> <note>No comment provided by engineer.</note> </trans-unit> + <trans-unit id="Invalid QR code" xml:space="preserve"> + <source>Invalid QR code</source> + <note>No comment provided by engineer.</note> + </trans-unit> <trans-unit id="Invalid connection link" xml:space="preserve"> <source>Invalid connection link</source> <target>Virheellinen yhteyslinkki</target> <note>No comment provided by engineer.</note> </trans-unit> + <trans-unit id="Invalid display name!" xml:space="preserve"> + <source>Invalid display name!</source> + <note>No comment provided by engineer.</note> + </trans-unit> + <trans-unit id="Invalid link" xml:space="preserve"> + <source>Invalid link</source> + <note>No comment provided by engineer.</note> + </trans-unit> <trans-unit id="Invalid name!" xml:space="preserve"> <source>Invalid name!</source> <note>No comment provided by engineer.</note> </trans-unit> + <trans-unit id="Invalid response" xml:space="preserve"> + <source>Invalid response</source> + <note>No comment provided by engineer.</note> + </trans-unit> <trans-unit id="Invalid server address!" xml:space="preserve"> <source>Invalid server address!</source> <target>Virheellinen palvelinosoite!</target> @@ -3001,6 +3065,10 @@ This cannot be undone!</source> <target>Liity ryhmään</target> <note>No comment provided by engineer.</note> </trans-unit> + <trans-unit id="Join group conversations" xml:space="preserve"> + <source>Join group conversations</source> + <note>No comment provided by engineer.</note> + </trans-unit> <trans-unit id="Join group?" xml:space="preserve"> <source>Join group?</source> <note>No comment provided by engineer.</note> @@ -3024,10 +3092,18 @@ This is your link for group %@!</source> <target>Liittyy ryhmään</target> <note>No comment provided by engineer.</note> </trans-unit> + <trans-unit id="Keep" xml:space="preserve"> + <source>Keep</source> + <note>No comment provided by engineer.</note> + </trans-unit> <trans-unit id="Keep the app open to use it from desktop" xml:space="preserve"> <source>Keep the app open to use it from desktop</source> <note>No comment provided by engineer.</note> </trans-unit> + <trans-unit id="Keep unused invitation?" xml:space="preserve"> + <source>Keep unused invitation?</source> + <note>No comment provided by engineer.</note> + </trans-unit> <trans-unit id="Keep your connections" xml:space="preserve"> <source>Keep your connections</source> <target>Pidä kontaktisi</target> @@ -3110,6 +3186,11 @@ This is your link for group %@!</source> <target>Live-viestit</target> <note>No comment provided by engineer.</note> </trans-unit> + <trans-unit id="Local" xml:space="preserve"> + <source>Local</source> + <target>Paikallinen</target> + <note>No comment provided by engineer.</note> + </trans-unit> <trans-unit id="Local name" xml:space="preserve"> <source>Local name</source> <target>Paikallinen nimi</target> @@ -3349,6 +3430,10 @@ This is your link for group %@!</source> <target>Uusi pääsykoodi</target> <note>No comment provided by engineer.</note> </trans-unit> + <trans-unit id="New chat" xml:space="preserve"> + <source>New chat</source> + <note>No comment provided by engineer.</note> + </trans-unit> <trans-unit id="New contact request" xml:space="preserve"> <source>New contact request</source> <target>Uusi kontaktipyyntö</target> @@ -3471,16 +3556,15 @@ This is your link for group %@!</source> - poista jäsenet käytöstä ("tarkkailija" rooli)</target> <note>No comment provided by engineer.</note> </trans-unit> + <trans-unit id="OK" xml:space="preserve"> + <source>OK</source> + <note>No comment provided by engineer.</note> + </trans-unit> <trans-unit id="Off" xml:space="preserve"> <source>Off</source> <target>Pois</target> <note>No comment provided by engineer.</note> </trans-unit> - <trans-unit id="Off (Local)" xml:space="preserve"> - <source>Off (Local)</source> - <target>Pois (Paikallinen)</target> - <note>No comment provided by engineer.</note> - </trans-unit> <trans-unit id="Ok" xml:space="preserve"> <source>Ok</source> <target>Ok</target> @@ -3541,9 +3625,9 @@ This is your link for group %@!</source> <target>Vain sinä voit lisätä viestireaktioita.</target> <note>No comment provided by engineer.</note> </trans-unit> - <trans-unit id="Only you can irreversibly delete messages (your contact can mark them for deletion)." xml:space="preserve"> - <source>Only you can irreversibly delete messages (your contact can mark them for deletion).</source> - <target>Vain sinä voit poistaa viestejä peruuttamattomasti (kontaktisi voi merkitä ne poistettavaksi).</target> + <trans-unit id="Only you can irreversibly delete messages (your contact can mark them for deletion). (24 hours)" xml:space="preserve"> + <source>Only you can irreversibly delete messages (your contact can mark them for deletion). (24 hours)</source> + <target>Vain sinä voit poistaa viestejä peruuttamattomasti (kontaktisi voi merkitä ne poistettavaksi). (24 tuntia)</target> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="Only you can make calls." xml:space="preserve"> @@ -3566,9 +3650,9 @@ This is your link for group %@!</source> <target>Vain kontaktisi voi lisätä viestireaktioita.</target> <note>No comment provided by engineer.</note> </trans-unit> - <trans-unit id="Only your contact can irreversibly delete messages (you can mark them for deletion)." xml:space="preserve"> - <source>Only your contact can irreversibly delete messages (you can mark them for deletion).</source> - <target>Vain kontaktisi voi poistaa viestejä peruuttamattomasti (voit merkitä ne poistettavaksi).</target> + <trans-unit id="Only your contact can irreversibly delete messages (you can mark them for deletion). (24 hours)" xml:space="preserve"> + <source>Only your contact can irreversibly delete messages (you can mark them for deletion). (24 hours)</source> + <target>Vain kontaktisi voi poistaa viestejä peruuttamattomasti (voit merkitä ne poistettavaksi). (24 tuntia)</target> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="Only your contact can make calls." xml:space="preserve"> @@ -3619,9 +3703,16 @@ This is your link for group %@!</source> <target>Avoimen lähdekoodin protokolla ja koodi - kuka tahansa voi käyttää palvelimia.</target> <note>No comment provided by engineer.</note> </trans-unit> - <trans-unit id="Opening database…" xml:space="preserve"> - <source>Opening database…</source> - <target>Avataan tietokantaa…</target> + <trans-unit id="Opening app…" xml:space="preserve"> + <source>Opening app…</source> + <note>No comment provided by engineer.</note> + </trans-unit> + <trans-unit id="Or scan QR code" xml:space="preserve"> + <source>Or scan QR code</source> + <note>No comment provided by engineer.</note> + </trans-unit> + <trans-unit id="Or show this code" xml:space="preserve"> + <source>Or show this code</source> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="PING count" xml:space="preserve"> @@ -3664,10 +3755,9 @@ This is your link for group %@!</source> <target>Salasana näytettäväksi</target> <note>No comment provided by engineer.</note> </trans-unit> - <trans-unit id="Paste" xml:space="preserve"> - <source>Paste</source> - <target>Liitä</target> - <note>No comment provided by engineer.</note> + <trans-unit id="Past member %@" xml:space="preserve"> + <source>Past member %@</source> + <note>past/unknown group member</note> </trans-unit> <trans-unit id="Paste desktop address" xml:space="preserve"> <source>Paste desktop address</source> @@ -3678,15 +3768,13 @@ This is your link for group %@!</source> <target>Liitä kuva</target> <note>No comment provided by engineer.</note> </trans-unit> - <trans-unit id="Paste received link" xml:space="preserve"> - <source>Paste received link</source> - <target>Liitä vastaanotettu linkki</target> + <trans-unit id="Paste link to connect!" xml:space="preserve"> + <source>Paste link to connect!</source> <note>No comment provided by engineer.</note> </trans-unit> - <trans-unit id="Paste the link you received to connect with your contact." xml:space="preserve"> - <source>Paste the link you received to connect with your contact.</source> - <target>Liitä saamasi linkki, jonka avulla voit muodostaa yhteyden kontaktiisi.</target> - <note>placeholder</note> + <trans-unit id="Paste the link you received" xml:space="preserve"> + <source>Paste the link you received</source> + <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="People can connect to you only via the links you share." xml:space="preserve"> <source>People can connect to you only via the links you share.</source> @@ -3723,6 +3811,11 @@ This is your link for group %@!</source> <target>Tarkista omasi ja kontaktin asetukset.</target> <note>No comment provided by engineer.</note> </trans-unit> + <trans-unit id="Please contact developers. Error: %@" xml:space="preserve"> + <source>Please contact developers. +Error: %@</source> + <note>No comment provided by engineer.</note> + </trans-unit> <trans-unit id="Please contact group admin." xml:space="preserve"> <source>Please contact group admin.</source> <target>Ota yhteyttä ryhmän ylläpitäjään.</target> @@ -3808,6 +3901,10 @@ This is your link for group %@!</source> <target>Yksityiset tiedostonimet</target> <note>No comment provided by engineer.</note> </trans-unit> + <trans-unit id="Private notes" xml:space="preserve"> + <source>Private notes</source> + <note>name of notes to self</note> + </trans-unit> <trans-unit id="Profile and server connections" xml:space="preserve"> <source>Profile and server connections</source> <target>Profiili- ja palvelinyhteydet</target> @@ -3926,6 +4023,10 @@ This is your link for group %@!</source> <target>Lue lisää [Käyttöoppaasta](https://simplex.chat/docs/guide/app-settings.html#your-simplex-contact-address).</target> <note>No comment provided by engineer.</note> </trans-unit> + <trans-unit id="Read more in [User Guide](https://simplex.chat/docs/guide/chat-profiles.html#incognito-mode)." xml:space="preserve"> + <source>Read more in [User Guide](https://simplex.chat/docs/guide/chat-profiles.html#incognito-mode).</source> + <note>No comment provided by engineer.</note> + </trans-unit> <trans-unit id="Read more in [User Guide](https://simplex.chat/docs/guide/readme.html#connect-to-friends)." xml:space="preserve"> <source>Read more in [User Guide](https://simplex.chat/docs/guide/readme.html#connect-to-friends).</source> <target>Lue lisää [Käyttöoppaasta](https://simplex.chat/docs/guide/readme.html#connect-to-friends).</target> @@ -3981,6 +4082,10 @@ This is your link for group %@!</source> <target>Vastaanotto kautta</target> <note>No comment provided by engineer.</note> </trans-unit> + <trans-unit id="Recent history and improved [directory bot](simplex:/contact#/?v=1-4&smp=smp%3A%2F%2Fu2dS9sG8nMNURyZwqASV4yROM28Er0luVTx5X1CsMrU%3D%40smp4.simplex.im%2FeXSPwqTkKyDO3px4fLf1wx3MvPdjdLW3%23%2F%3Fv%3D1-2%26dh%3DMCowBQYDK2VuAyEAaiv6MkMH44L2TcYrt_CsX3ZvM11WgbMEUn0hkIKTOho%253D%26srv%3Do5vmywmrnaxalvz6wi3zicyftgio6psuvyniis6gco6bp6ekl4cqj4id.onion)." xml:space="preserve"> + <source>Recent history and improved [directory bot](simplex:/contact#/?v=1-4&smp=smp%3A%2F%2Fu2dS9sG8nMNURyZwqASV4yROM28Er0luVTx5X1CsMrU%3D%40smp4.simplex.im%2FeXSPwqTkKyDO3px4fLf1wx3MvPdjdLW3%23%2F%3Fv%3D1-2%26dh%3DMCowBQYDK2VuAyEAaiv6MkMH44L2TcYrt_CsX3ZvM11WgbMEUn0hkIKTOho%253D%26srv%3Do5vmywmrnaxalvz6wi3zicyftgio6psuvyniis6gco6bp6ekl4cqj4id.onion).</source> + <note>No comment provided by engineer.</note> + </trans-unit> <trans-unit id="Recipients see updates as you type them." xml:space="preserve"> <source>Recipients see updates as you type them.</source> <target>Vastaanottajat näkevät päivitykset, kun kirjoitat niitä.</target> @@ -4134,6 +4239,10 @@ This is your link for group %@!</source> <target>Virhe tietokannan palauttamisessa</target> <note>No comment provided by engineer.</note> </trans-unit> + <trans-unit id="Retry" xml:space="preserve"> + <source>Retry</source> + <note>No comment provided by engineer.</note> + </trans-unit> <trans-unit id="Reveal" xml:space="preserve"> <source>Reveal</source> <target>Paljasta</target> @@ -4259,6 +4368,10 @@ This is your link for group %@!</source> <target>Tallennetut WebRTC ICE -palvelimet poistetaan</target> <note>No comment provided by engineer.</note> </trans-unit> + <trans-unit id="Saved message" xml:space="preserve"> + <source>Saved message</source> + <note>message info title</note> + </trans-unit> <trans-unit id="Scan QR code" xml:space="preserve"> <source>Scan QR code</source> <target>Skannaa QR-koodi</target> @@ -4288,6 +4401,14 @@ This is your link for group %@!</source> <target>Haku</target> <note>No comment provided by engineer.</note> </trans-unit> + <trans-unit id="Search bar accepts invitation links." xml:space="preserve"> + <source>Search bar accepts invitation links.</source> + <note>No comment provided by engineer.</note> + </trans-unit> + <trans-unit id="Search or paste SimpleX link" xml:space="preserve"> + <source>Search or paste SimpleX link</source> + <note>No comment provided by engineer.</note> + </trans-unit> <trans-unit id="Secure queue" xml:space="preserve"> <source>Secure queue</source> <target>Turvallinen jono</target> @@ -4392,6 +4513,10 @@ This is your link for group %@!</source> <target>Lähetä ne galleriasta tai mukautetuista näppäimistöistä.</target> <note>No comment provided by engineer.</note> </trans-unit> + <trans-unit id="Send up to 100 last messages to new members." xml:space="preserve"> + <source>Send up to 100 last messages to new members.</source> + <note>No comment provided by engineer.</note> + </trans-unit> <trans-unit id="Sender cancelled file transfer." xml:space="preserve"> <source>Sender cancelled file transfer.</source> <target>Lähettäjä peruutti tiedoston siirron.</target> @@ -4561,9 +4686,8 @@ This is your link for group %@!</source> <target>Jaa linkki</target> <note>No comment provided by engineer.</note> </trans-unit> - <trans-unit id="Share one-time invitation link" xml:space="preserve"> - <source>Share one-time invitation link</source> - <target>Jaa kertakutsulinkki</target> + <trans-unit id="Share this 1-time invite link" xml:space="preserve"> + <source>Share this 1-time invite link</source> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="Share with contacts" xml:space="preserve"> @@ -4685,16 +4809,15 @@ This is your link for group %@!</source> <target>Joku</target> <note>notification title</note> </trans-unit> - <trans-unit id="Start a new chat" xml:space="preserve"> - <source>Start a new chat</source> - <target>Aloita uusi keskustelu</target> - <note>No comment provided by engineer.</note> - </trans-unit> <trans-unit id="Start chat" xml:space="preserve"> <source>Start chat</source> <target>Aloita keskustelu</target> <note>No comment provided by engineer.</note> </trans-unit> + <trans-unit id="Start chat?" xml:space="preserve"> + <source>Start chat?</source> + <note>No comment provided by engineer.</note> + </trans-unit> <trans-unit id="Start migration" xml:space="preserve"> <source>Start migration</source> <target>Aloita siirto</target> @@ -4819,6 +4942,14 @@ This is your link for group %@!</source> <target>Napauta liittyäksesi incognito-tilassa</target> <note>No comment provided by engineer.</note> </trans-unit> + <trans-unit id="Tap to paste link" xml:space="preserve"> + <source>Tap to paste link</source> + <note>No comment provided by engineer.</note> + </trans-unit> + <trans-unit id="Tap to scan" xml:space="preserve"> + <source>Tap to scan</source> + <note>No comment provided by engineer.</note> + </trans-unit> <trans-unit id="Tap to start a new chat" xml:space="preserve"> <source>Tap to start a new chat</source> <target>Aloita uusi keskustelu napauttamalla</target> @@ -4881,6 +5012,10 @@ Tämä voi johtua jostain virheestä tai siitä, että yhteys on vaarantunut.</t <target>Tietokannan tunnuslauseen muuttamista ei suoritettu loppuun.</target> <note>No comment provided by engineer.</note> </trans-unit> + <trans-unit id="The code you scanned is not a SimpleX link QR code." xml:space="preserve"> + <source>The code you scanned is not a SimpleX link QR code.</source> + <note>No comment provided by engineer.</note> + </trans-unit> <trans-unit id="The connection you accepted will be cancelled!" xml:space="preserve"> <source>The connection you accepted will be cancelled!</source> <target>Hyväksymäsi yhteys peruuntuu!</target> @@ -4946,21 +5081,15 @@ Tämä voi johtua jostain virheestä tai siitä, että yhteys on vaarantunut.</t <target>Palvelimet nykyisen keskusteluprofiilisi uusille yhteyksille **%@**.</target> <note>No comment provided by engineer.</note> </trans-unit> + <trans-unit id="The text you pasted is not a SimpleX link." xml:space="preserve"> + <source>The text you pasted is not a SimpleX link.</source> + <note>No comment provided by engineer.</note> + </trans-unit> <trans-unit id="Theme" xml:space="preserve"> <source>Theme</source> <target>Teema</target> <note>No comment provided by engineer.</note> </trans-unit> - <trans-unit id="There should be at least one user profile." xml:space="preserve"> - <source>There should be at least one user profile.</source> - <target>Käyttäjäprofiileja tulee olla vähintään yksi.</target> - <note>No comment provided by engineer.</note> - </trans-unit> - <trans-unit id="There should be at least one visible user profile." xml:space="preserve"> - <source>There should be at least one visible user profile.</source> - <target>Näkyviä käyttäjäprofiileja tulee olla vähintään yksi.</target> - <note>No comment provided by engineer.</note> - </trans-unit> <trans-unit id="These settings are for your current profile **%@**." xml:space="preserve"> <source>These settings are for your current profile **%@**.</source> <target>Nämä asetukset koskevat nykyistä profiiliasi **%@**.</target> @@ -4990,6 +5119,10 @@ Tämä voi johtua jostain virheestä tai siitä, että yhteys on vaarantunut.</t <source>This device name</source> <note>No comment provided by engineer.</note> </trans-unit> + <trans-unit id="This display name is invalid. Please choose another name." xml:space="preserve"> + <source>This display name is invalid. Please choose another name.</source> + <note>No comment provided by engineer.</note> + </trans-unit> <trans-unit id="This group has over %lld members, delivery receipts are not sent." xml:space="preserve"> <source>This group has over %lld members, delivery receipts are not sent.</source> <target>Tässä ryhmässä on yli %lld jäsentä, lähetyskuittauksia ei lähetetä.</target> @@ -5088,16 +5221,15 @@ Sinua kehotetaan suorittamaan todennus loppuun, ennen kuin tämä ominaisuus ote <target>Yritetään muodostaa yhteys palvelimeen, jota käytetään viestien vastaanottamiseen tältä kontaktilta.</target> <note>No comment provided by engineer.</note> </trans-unit> + <trans-unit id="Turkish interface" xml:space="preserve"> + <source>Turkish interface</source> + <note>No comment provided by engineer.</note> + </trans-unit> <trans-unit id="Turn off" xml:space="preserve"> <source>Turn off</source> <target>Sammuta</target> <note>No comment provided by engineer.</note> </trans-unit> - <trans-unit id="Turn off notifications?" xml:space="preserve"> - <source>Turn off notifications?</source> - <target>Kytke ilmoitukset pois päältä?</target> - <note>No comment provided by engineer.</note> - </trans-unit> <trans-unit id="Turn on" xml:space="preserve"> <source>Turn on</source> <target>Kytke päälle</target> @@ -5112,10 +5244,18 @@ Sinua kehotetaan suorittamaan todennus loppuun, ennen kuin tämä ominaisuus ote <source>Unblock</source> <note>No comment provided by engineer.</note> </trans-unit> + <trans-unit id="Unblock for all" xml:space="preserve"> + <source>Unblock for all</source> + <note>No comment provided by engineer.</note> + </trans-unit> <trans-unit id="Unblock member" xml:space="preserve"> <source>Unblock member</source> <note>No comment provided by engineer.</note> </trans-unit> + <trans-unit id="Unblock member for all?" xml:space="preserve"> + <source>Unblock member for all?</source> + <note>No comment provided by engineer.</note> + </trans-unit> <trans-unit id="Unblock member?" xml:space="preserve"> <source>Unblock member?</source> <note>No comment provided by engineer.</note> @@ -5210,6 +5350,10 @@ Jos haluat muodostaa yhteyden, pyydä kontaktiasi luomaan toinen yhteyslinkki ja <target>Lukematon</target> <note>No comment provided by engineer.</note> </trans-unit> + <trans-unit id="Up to 100 last messages are sent to new members." xml:space="preserve"> + <source>Up to 100 last messages are sent to new members.</source> + <note>No comment provided by engineer.</note> + </trans-unit> <trans-unit id="Update" xml:space="preserve"> <source>Update</source> <target>Päivitä</target> @@ -5294,6 +5438,10 @@ Jos haluat muodostaa yhteyden, pyydä kontaktiasi luomaan toinen yhteyslinkki ja <target>Käytä uutta incognito-profiilia</target> <note>No comment provided by engineer.</note> </trans-unit> + <trans-unit id="Use only local notifications?" xml:space="preserve"> + <source>Use only local notifications?</source> + <note>No comment provided by engineer.</note> + </trans-unit> <trans-unit id="Use server" xml:space="preserve"> <source>Use server</source> <target>Käytä palvelinta</target> @@ -5370,6 +5518,10 @@ Jos haluat muodostaa yhteyden, pyydä kontaktiasi luomaan toinen yhteyslinkki ja <target>Näytä turvakoodi</target> <note>No comment provided by engineer.</note> </trans-unit> + <trans-unit id="Visible history" xml:space="preserve"> + <source>Visible history</source> + <note>chat feature</note> + </trans-unit> <trans-unit id="Voice messages" xml:space="preserve"> <source>Voice messages</source> <target>Ääniviestit</target> @@ -5454,11 +5606,19 @@ Jos haluat muodostaa yhteyden, pyydä kontaktiasi luomaan toinen yhteyslinkki ja <target>Kun jaat inkognitoprofiilin jonkun kanssa, tätä profiilia käytetään ryhmissä, joihin tämä sinut kutsuu.</target> <note>No comment provided by engineer.</note> </trans-unit> + <trans-unit id="With encrypted files and media." xml:space="preserve"> + <source>With encrypted files and media.</source> + <note>No comment provided by engineer.</note> + </trans-unit> <trans-unit id="With optional welcome message." xml:space="preserve"> <source>With optional welcome message.</source> <target>Valinnaisella tervetuloviestillä.</target> <note>No comment provided by engineer.</note> </trans-unit> + <trans-unit id="With reduced battery usage." xml:space="preserve"> + <source>With reduced battery usage.</source> + <note>No comment provided by engineer.</note> + </trans-unit> <trans-unit id="Wrong database passphrase" xml:space="preserve"> <source>Wrong database passphrase</source> <target>Väärä tietokannan tunnuslause</target> @@ -5543,11 +5703,6 @@ Repeat join request?</source> <target>Voit vastaanottaa puheluita lukitusnäytöltä ilman laitteen ja sovelluksen todennusta.</target> <note>No comment provided by engineer.</note> </trans-unit> - <trans-unit id="You can also connect by clicking the link. If it opens in the browser, click **Open in mobile app** button." xml:space="preserve"> - <source>You can also connect by clicking the link. If it opens in the browser, click **Open in mobile app** button.</source> - <target>Voit myös muodostaa yhteyden klikkaamalla linkkiä. Jos se avautuu selaimessa, napsauta **Avaa mobiilisovelluksessa**-painiketta.</target> - <note>No comment provided by engineer.</note> - </trans-unit> <trans-unit id="You can create it later" xml:space="preserve"> <source>You can create it later</source> <target>Voit luoda sen myöhemmin</target> @@ -5568,6 +5723,10 @@ Repeat join request?</source> <target>Voit piilottaa tai mykistää käyttäjäprofiilin pyyhkäisemällä sitä oikealle.</target> <note>No comment provided by engineer.</note> </trans-unit> + <trans-unit id="You can make it visible to your SimpleX contacts via Settings." xml:space="preserve"> + <source>You can make it visible to your SimpleX contacts via Settings.</source> + <note>No comment provided by engineer.</note> + </trans-unit> <trans-unit id="You can now send messages to %@" xml:space="preserve"> <source>You can now send messages to %@</source> <target>Voit nyt lähettää viestejä %@:lle</target> @@ -5608,6 +5767,10 @@ Repeat join request?</source> <target>Voit käyttää markdownia viestien muotoiluun:</target> <note>No comment provided by engineer.</note> </trans-unit> + <trans-unit id="You can view invitation link again in connection details." xml:space="preserve"> + <source>You can view invitation link again in connection details.</source> + <note>No comment provided by engineer.</note> + </trans-unit> <trans-unit id="You can't send messages!" xml:space="preserve"> <source>You can't send messages!</source> <target>Et voi lähettää viestejä!</target> @@ -5792,13 +5955,6 @@ Voit peruuttaa tämän yhteyden ja poistaa kontaktin (ja yrittää myöhemmin uu <target>Kontaktisi voivat sallia viestien täydellisen poistamisen.</target> <note>No comment provided by engineer.</note> </trans-unit> - <trans-unit id="Your contacts in SimpleX will see it. You can change it in Settings." xml:space="preserve"> - <source>Your contacts in SimpleX will see it. -You can change it in Settings.</source> - <target>Kontaktisi SimpleX:ssä näkevät sen. -Voit muuttaa sitä Asetuksista.</target> - <note>No comment provided by engineer.</note> - </trans-unit> <trans-unit id="Your contacts will remain connected." xml:space="preserve"> <source>Your contacts will remain connected.</source> <target>Kontaktisi pysyvät yhdistettyinä.</target> @@ -5947,6 +6103,14 @@ SimpleX-palvelimet eivät näe profiiliasi.</target> <source>blocked</source> <note>No comment provided by engineer.</note> </trans-unit> + <trans-unit id="blocked %@" xml:space="preserve"> + <source>blocked %@</source> + <note>rcv group event chat item</note> + </trans-unit> + <trans-unit id="blocked by admin" xml:space="preserve"> + <source>blocked by admin</source> + <note>blocked chat item</note> + </trans-unit> <trans-unit id="bold" xml:space="preserve"> <source>bold</source> <target>lihavoitu</target> @@ -6066,6 +6230,10 @@ SimpleX-palvelimet eivät näe profiiliasi.</target> <target>yhteys:%@</target> <note>connection information</note> </trans-unit> + <trans-unit id="contact %@ changed to %@" xml:space="preserve"> + <source>contact %1$@ changed to %2$@</source> + <note>profile update event chat item</note> + </trans-unit> <trans-unit id="contact has e2e encryption" xml:space="preserve"> <source>contact has e2e encryption</source> <target>kontaktilla on e2e-salaus</target> @@ -6335,6 +6503,10 @@ SimpleX-palvelimet eivät näe profiiliasi.</target> <target>jäsen</target> <note>member role</note> </trans-unit> + <trans-unit id="member %@ changed to %@" xml:space="preserve"> + <source>member %1$@ changed to %2$@</source> + <note>profile update event chat item</note> + </trans-unit> <trans-unit id="member connected" xml:space="preserve"> <source>connected</source> <target>yhdistetty</target> @@ -6457,6 +6629,14 @@ SimpleX-palvelimet eivät näe profiiliasi.</target> <target>%@ poistettu</target> <note>rcv group event chat item</note> </trans-unit> + <trans-unit id="removed contact address" xml:space="preserve"> + <source>removed contact address</source> + <note>profile update event chat item</note> + </trans-unit> + <trans-unit id="removed profile picture" xml:space="preserve"> + <source>removed profile picture</source> + <note>profile update event chat item</note> + </trans-unit> <trans-unit id="removed you" xml:space="preserve"> <source>removed you</source> <target>poisti sinut</target> @@ -6486,6 +6666,14 @@ SimpleX-palvelimet eivät näe profiiliasi.</target> <source>send direct message</source> <note>No comment provided by engineer.</note> </trans-unit> + <trans-unit id="set new contact address" xml:space="preserve"> + <source>set new contact address</source> + <note>profile update event chat item</note> + </trans-unit> + <trans-unit id="set new profile picture" xml:space="preserve"> + <source>set new profile picture</source> + <note>profile update event chat item</note> + </trans-unit> <trans-unit id="starting…" xml:space="preserve"> <source>starting…</source> <target>alkaa…</target> @@ -6501,16 +6689,28 @@ SimpleX-palvelimet eivät näe profiiliasi.</target> <target>tämä kontakti</target> <note>notification title</note> </trans-unit> + <trans-unit id="unblocked %@" xml:space="preserve"> + <source>unblocked %@</source> + <note>rcv group event chat item</note> + </trans-unit> <trans-unit id="unknown" xml:space="preserve"> <source>unknown</source> <target>tuntematon</target> <note>connection info</note> </trans-unit> + <trans-unit id="unknown status" xml:space="preserve"> + <source>unknown status</source> + <note>No comment provided by engineer.</note> + </trans-unit> <trans-unit id="updated group profile" xml:space="preserve"> <source>updated group profile</source> <target>päivitetty ryhmäprofiili</target> <note>rcv group event chat item</note> </trans-unit> + <trans-unit id="updated profile" xml:space="preserve"> + <source>updated profile</source> + <note>profile update event chat item</note> + </trans-unit> <trans-unit id="v%@" xml:space="preserve"> <source>v%@</source> <note>No comment provided by engineer.</note> @@ -6580,6 +6780,10 @@ SimpleX-palvelimet eivät näe profiiliasi.</target> <target>olet tarkkailija</target> <note>No comment provided by engineer.</note> </trans-unit> + <trans-unit id="you blocked %@" xml:space="preserve"> + <source>you blocked %@</source> + <note>snd group event chat item</note> + </trans-unit> <trans-unit id="you changed address" xml:space="preserve"> <source>you changed address</source> <target>muutit osoitetta</target> @@ -6620,6 +6824,10 @@ SimpleX-palvelimet eivät näe profiiliasi.</target> <target>jaoit kertalinkin incognito-tilassa</target> <note>chat list item description</note> </trans-unit> + <trans-unit id="you unblocked %@" xml:space="preserve"> + <source>you unblocked %@</source> + <note>snd group event chat item</note> + </trans-unit> <trans-unit id="you: " xml:space="preserve"> <source>you: </source> <target>sinä: </target> diff --git a/apps/ios/SimpleX Localizations/fr.xcloc/Localized Contents/fr.xliff b/apps/ios/SimpleX Localizations/fr.xcloc/Localized Contents/fr.xliff index 153d98be3c..12c10dd0c8 100644 --- a/apps/ios/SimpleX Localizations/fr.xcloc/Localized Contents/fr.xliff +++ b/apps/ios/SimpleX Localizations/fr.xcloc/Localized Contents/fr.xliff @@ -217,6 +217,10 @@ <target>%lld messages bloqués</target> <note>No comment provided by engineer.</note> </trans-unit> + <trans-unit id="%lld messages blocked by admin" xml:space="preserve"> + <source>%lld messages blocked by admin</source> + <note>No comment provided by engineer.</note> + </trans-unit> <trans-unit id="%lld messages marked deleted" xml:space="preserve"> <source>%lld messages marked deleted</source> <target>%lld messages marqués comme supprimés</target> @@ -312,14 +316,19 @@ <target>)</target> <note>No comment provided by engineer.</note> </trans-unit> + <trans-unit id="**Add contact**: to create a new invitation link, or connect via a link you received." xml:space="preserve"> + <source>**Add contact**: to create a new invitation link, or connect via a link you received.</source> + <target>**Ajouter un contact** : pour créer un nouveau lien d'invitation ou vous connecter via un lien que vous avez reçu.</target> + <note>No comment provided by engineer.</note> + </trans-unit> <trans-unit id="**Add new contact**: to create your one-time QR Code for your contact." xml:space="preserve"> <source>**Add new contact**: to create your one-time QR Code or link for your contact.</source> <target>**Ajouter un nouveau contact** : pour créer un lien ou code QR unique pour votre contact.</target> <note>No comment provided by engineer.</note> </trans-unit> - <trans-unit id="**Create link / QR code** for your contact to use." xml:space="preserve"> - <source>**Create link / QR code** for your contact to use.</source> - <target>**Créer un lien / code QR** que votre contact pourra utiliser.</target> + <trans-unit id="**Create group**: to create a new group." xml:space="preserve"> + <source>**Create group**: to create a new group.</source> + <target>**Créer un groupe** : pour créer un nouveau groupe.</target> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="**More private**: check new messages every 20 minutes. Device token is shared with SimpleX Chat server, but not how many contacts or messages you have." xml:space="preserve"> @@ -332,11 +341,6 @@ <target>**Confidentiel** : ne pas utiliser le serveur de notifications SimpleX, vérification de nouveaux messages periodiquement en arrière plan (dépend de l'utilisation de l'app).</target> <note>No comment provided by engineer.</note> </trans-unit> - <trans-unit id="**Paste received link** or open it in the browser and tap **Open in mobile app**." xml:space="preserve"> - <source>**Paste received link** or open it in the browser and tap **Open in mobile app**.</source> - <target>**Collez le lien reçu** ou ouvrez-le dans votre navigateur et appuyez sur **Open in mobile app**.</target> - <note>No comment provided by engineer.</note> - </trans-unit> <trans-unit id="**Please note**: you will NOT be able to recover or change passphrase if you lose it." xml:space="preserve"> <source>**Please note**: you will NOT be able to recover or change passphrase if you lose it.</source> <target>**Veuillez noter** : vous NE pourrez PAS récupérer ou modifier votre phrase secrète si vous la perdez.</target> @@ -347,11 +351,6 @@ <target>**Recommandé** : le token de l'appareil et les notifications sont envoyés au serveur de notifications SimpleX, mais pas le contenu du message, sa taille ou son auteur.</target> <note>No comment provided by engineer.</note> </trans-unit> - <trans-unit id="**Scan QR code**: to connect to your contact in person or via video call." xml:space="preserve"> - <source>**Scan QR code**: to connect to your contact in person or via video call.</source> - <target>**Scanner le code QR** : pour vous connecter à votre contact en personne ou par appel vidéo.</target> - <note>No comment provided by engineer.</note> - </trans-unit> <trans-unit id="**Warning**: Instant push notifications require passphrase saved in Keychain." xml:space="preserve"> <source>**Warning**: Instant push notifications require passphrase saved in Keychain.</source> <target>**Avertissement** : les notifications push instantanées nécessitent une phrase secrète enregistrée dans la keychain.</target> @@ -453,11 +452,6 @@ <target>1 semaine</target> <note>time interval</note> </trans-unit> - <trans-unit id="1-time link" xml:space="preserve"> - <source>1-time link</source> - <target>Lien à usage unique</target> - <note>No comment provided by engineer.</note> - </trans-unit> <trans-unit id="5 minutes" xml:space="preserve"> <source>5 minutes</source> <target>5 minutes</target> @@ -573,6 +567,11 @@ <target>Ajoutez une adresse à votre profil, afin que vos contacts puissent la partager avec d'autres personnes. La mise à jour du profil sera envoyée à vos contacts.</target> <note>No comment provided by engineer.</note> </trans-unit> + <trans-unit id="Add contact" xml:space="preserve"> + <source>Add contact</source> + <target>Ajouter le contact</target> + <note>No comment provided by engineer.</note> + </trans-unit> <trans-unit id="Add preset servers" xml:space="preserve"> <source>Add preset servers</source> <target>Ajouter des serveurs prédéfinis</target> @@ -643,6 +642,11 @@ <target>Tous les membres du groupe resteront connectés.</target> <note>No comment provided by engineer.</note> </trans-unit> + <trans-unit id="All messages will be deleted - this cannot be undone!" xml:space="preserve"> + <source>All messages will be deleted - this cannot be undone!</source> + <target>Tous les messages seront supprimés - il n'est pas possible de revenir en arrière !</target> + <note>No comment provided by engineer.</note> + </trans-unit> <trans-unit id="All messages will be deleted - this cannot be undone! The messages will be deleted ONLY for you." xml:space="preserve"> <source>All messages will be deleted - this cannot be undone! The messages will be deleted ONLY for you.</source> <target>Tous les messages seront supprimés - impossible de revenir en arrière ! Les messages seront supprimés UNIQUEMENT pour vous.</target> @@ -678,9 +682,9 @@ <target>Autorise les messages éphémères seulement si votre contact vous l’autorise.</target> <note>No comment provided by engineer.</note> </trans-unit> - <trans-unit id="Allow irreversible message deletion only if your contact allows it to you." xml:space="preserve"> - <source>Allow irreversible message deletion only if your contact allows it to you.</source> - <target>Autoriser la suppression irréversible des messages uniquement si votre contact vous l'autorise.</target> + <trans-unit id="Allow irreversible message deletion only if your contact allows it to you. (24 hours)" xml:space="preserve"> + <source>Allow irreversible message deletion only if your contact allows it to you. (24 hours)</source> + <target>Autoriser la suppression irréversible des messages uniquement si votre contact vous l'autorise. (24 heures)</target> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="Allow message reactions only if your contact allows them." xml:space="preserve"> @@ -703,9 +707,9 @@ <target>Autorise l’envoi de messages éphémères.</target> <note>No comment provided by engineer.</note> </trans-unit> - <trans-unit id="Allow to irreversibly delete sent messages." xml:space="preserve"> - <source>Allow to irreversibly delete sent messages.</source> - <target>Autoriser la suppression irréversible de messages envoyés.</target> + <trans-unit id="Allow to irreversibly delete sent messages. (24 hours)" xml:space="preserve"> + <source>Allow to irreversibly delete sent messages. (24 hours)</source> + <target>Autoriser la suppression irréversible de messages envoyés. (24 heures)</target> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="Allow to send files and media." xml:space="preserve"> @@ -738,9 +742,9 @@ <target>Autorise vos contacts à vous appeler.</target> <note>No comment provided by engineer.</note> </trans-unit> - <trans-unit id="Allow your contacts to irreversibly delete sent messages." xml:space="preserve"> - <source>Allow your contacts to irreversibly delete sent messages.</source> - <target>Autorise vos contacts à supprimer de manière irréversible les messages envoyés.</target> + <trans-unit id="Allow your contacts to irreversibly delete sent messages. (24 hours)" xml:space="preserve"> + <source>Allow your contacts to irreversibly delete sent messages. (24 hours)</source> + <target>Autorise vos contacts à supprimer de manière irréversible les messages envoyés. (24 heures)</target> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="Allow your contacts to send disappearing messages." xml:space="preserve"> @@ -918,6 +922,10 @@ <target>Bloquer</target> <note>No comment provided by engineer.</note> </trans-unit> + <trans-unit id="Block for all" xml:space="preserve"> + <source>Block for all</source> + <note>No comment provided by engineer.</note> + </trans-unit> <trans-unit id="Block group members" xml:space="preserve"> <source>Block group members</source> <target>Bloquer des membres d'un groupe</target> @@ -928,19 +936,27 @@ <target>Bloquer ce membre</target> <note>No comment provided by engineer.</note> </trans-unit> + <trans-unit id="Block member for all?" xml:space="preserve"> + <source>Block member for all?</source> + <note>No comment provided by engineer.</note> + </trans-unit> <trans-unit id="Block member?" xml:space="preserve"> <source>Block member?</source> <target>Bloquer ce membre ?</target> <note>No comment provided by engineer.</note> </trans-unit> + <trans-unit id="Blocked by admin" xml:space="preserve"> + <source>Blocked by admin</source> + <note>No comment provided by engineer.</note> + </trans-unit> <trans-unit id="Both you and your contact can add message reactions." xml:space="preserve"> <source>Both you and your contact can add message reactions.</source> <target>Vous et votre contact pouvez ajouter des réactions aux messages.</target> <note>No comment provided by engineer.</note> </trans-unit> - <trans-unit id="Both you and your contact can irreversibly delete sent messages." xml:space="preserve"> - <source>Both you and your contact can irreversibly delete sent messages.</source> - <target>Vous et votre contact êtes tous deux en mesure de supprimer de manière irréversible les messages envoyés.</target> + <trans-unit id="Both you and your contact can irreversibly delete sent messages. (24 hours)" xml:space="preserve"> + <source>Both you and your contact can irreversibly delete sent messages. (24 hours)</source> + <target>Vous et votre contact êtes tous deux en mesure de supprimer de manière irréversible les messages envoyés. (24 heures)</target> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="Both you and your contact can make calls." xml:space="preserve"> @@ -978,9 +994,9 @@ <target>Appels</target> <note>No comment provided by engineer.</note> </trans-unit> - <trans-unit id="Can't delete user profile!" xml:space="preserve"> - <source>Can't delete user profile!</source> - <target>Impossible de supprimer le profil d'utilisateur !</target> + <trans-unit id="Camera not available" xml:space="preserve"> + <source>Camera not available</source> + <target>Caméra non disponible</target> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="Can't invite contact!" xml:space="preserve"> @@ -1094,6 +1110,11 @@ <target>Le chat est arrêté</target> <note>No comment provided by engineer.</note> </trans-unit> + <trans-unit id="Chat is stopped. If you already used this database on another device, you should transfer it back before starting chat." xml:space="preserve"> + <source>Chat is stopped. If you already used this database on another device, you should transfer it back before starting chat.</source> + <target>Le chat est arrêté. Si vous avez déjà utilisé cette base de données sur un autre appareil, vous devez la transférer à nouveau avant de démarrer le chat.</target> + <note>No comment provided by engineer.</note> + </trans-unit> <trans-unit id="Chat preferences" xml:space="preserve"> <source>Chat preferences</source> <target>Préférences de chat</target> @@ -1101,7 +1122,7 @@ </trans-unit> <trans-unit id="Chats" xml:space="preserve"> <source>Chats</source> - <target>Chats</target> + <target>Discussions</target> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="Check server address and try again." xml:space="preserve"> @@ -1139,6 +1160,11 @@ <target>Effacer la conversation ?</target> <note>No comment provided by engineer.</note> </trans-unit> + <trans-unit id="Clear private notes?" xml:space="preserve"> + <source>Clear private notes?</source> + <target>Effacer les notes privées ?</target> + <note>No comment provided by engineer.</note> + </trans-unit> <trans-unit id="Clear verification" xml:space="preserve"> <source>Clear verification</source> <target>Retirer la vérification</target> @@ -1206,7 +1232,7 @@ </trans-unit> <trans-unit id="Connect to desktop" xml:space="preserve"> <source>Connect to desktop</source> - <target>Se connecter au bureau</target> + <target>Connexion au bureau</target> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="Connect to yourself?" xml:space="preserve"> @@ -1238,11 +1264,6 @@ Il s'agit de votre propre lien unique !</target> <target>Se connecter via un lien</target> <note>No comment provided by engineer.</note> </trans-unit> - <trans-unit id="Connect via link / QR code" xml:space="preserve"> - <source>Connect via link / QR code</source> - <target>Se connecter via un lien / code QR</target> - <note>No comment provided by engineer.</note> - </trans-unit> <trans-unit id="Connect via one-time link" xml:space="preserve"> <source>Connect via one-time link</source> <target>Se connecter via un lien unique</target> @@ -1418,11 +1439,6 @@ Il s'agit de votre propre lien unique !</target> <target>Créer un nouveau profil sur [l'application de bureau](https://simplex.chat/downloads/). 💻</target> <note>No comment provided by engineer.</note> </trans-unit> - <trans-unit id="Create one-time invitation link" xml:space="preserve"> - <source>Create one-time invitation link</source> - <target>Créer un lien d'invitation unique</target> - <note>No comment provided by engineer.</note> - </trans-unit> <trans-unit id="Create profile" xml:space="preserve"> <source>Create profile</source> <target>Créer le profil</target> @@ -1443,11 +1459,26 @@ Il s'agit de votre propre lien unique !</target> <target>Créez votre profil</target> <note>No comment provided by engineer.</note> </trans-unit> + <trans-unit id="Created at" xml:space="preserve"> + <source>Created at</source> + <target>Créé à</target> + <note>No comment provided by engineer.</note> + </trans-unit> + <trans-unit id="Created at: %@" xml:space="preserve"> + <source>Created at: %@</source> + <target>Créé à : %@</target> + <note>copied message info</note> + </trans-unit> <trans-unit id="Created on %@" xml:space="preserve"> <source>Created on %@</source> <target>Créé le %@</target> <note>No comment provided by engineer.</note> </trans-unit> + <trans-unit id="Creating link…" xml:space="preserve"> + <source>Creating link…</source> + <target>Création d'un lien…</target> + <note>No comment provided by engineer.</note> + </trans-unit> <trans-unit id="Current Passcode" xml:space="preserve"> <source>Current Passcode</source> <target>Code d'accès actuel</target> @@ -1928,6 +1959,11 @@ Cette opération ne peut être annulée !</target> <target>Faites-le plus tard</target> <note>No comment provided by engineer.</note> </trans-unit> + <trans-unit id="Do not send history to new members." xml:space="preserve"> + <source>Do not send history to new members.</source> + <target>Ne pas envoyer d'historique aux nouveaux membres.</target> + <note>No comment provided by engineer.</note> + </trans-unit> <trans-unit id="Don't create address" xml:space="preserve"> <source>Don't create address</source> <target>Ne pas créer d'adresse</target> @@ -1998,6 +2034,11 @@ Cette opération ne peut être annulée !</target> <target>Activer la suppression automatique des messages ?</target> <note>No comment provided by engineer.</note> </trans-unit> + <trans-unit id="Enable camera access" xml:space="preserve"> + <source>Enable camera access</source> + <target>Autoriser l'accès à la caméra</target> + <note>No comment provided by engineer.</note> + </trans-unit> <trans-unit id="Enable for all" xml:space="preserve"> <source>Enable for all</source> <target>Activer pour tous</target> @@ -2063,6 +2104,11 @@ Cette opération ne peut être annulée !</target> <target>Message chiffrée ou autre événement</target> <note>notification</note> </trans-unit> + <trans-unit id="Encrypted message: app is stopped" xml:space="preserve"> + <source>Encrypted message: app is stopped</source> + <target>Message chiffré : l'application est arrêtée</target> + <note>notification</note> + </trans-unit> <trans-unit id="Encrypted message: database error" xml:space="preserve"> <source>Encrypted message: database error</source> <target>Message chiffrée : erreur de base de données</target> @@ -2208,6 +2254,11 @@ Cette opération ne peut être annulée !</target> <target>Erreur lors de la création du contact du membre</target> <note>No comment provided by engineer.</note> </trans-unit> + <trans-unit id="Error creating message" xml:space="preserve"> + <source>Error creating message</source> + <target>Erreur lors de la création du message</target> + <note>No comment provided by engineer.</note> + </trans-unit> <trans-unit id="Error creating profile!" xml:space="preserve"> <source>Error creating profile!</source> <target>Erreur lors de la création du profil !</target> @@ -2293,6 +2344,11 @@ Cette opération ne peut être annulée !</target> <target>Erreur lors du chargement des serveurs %@</target> <note>No comment provided by engineer.</note> </trans-unit> + <trans-unit id="Error opening chat" xml:space="preserve"> + <source>Error opening chat</source> + <target>Erreur lors de l'ouverture du chat</target> + <note>No comment provided by engineer.</note> + </trans-unit> <trans-unit id="Error receiving file" xml:space="preserve"> <source>Error receiving file</source> <target>Erreur lors de la réception du fichier</target> @@ -2333,6 +2389,11 @@ Cette opération ne peut être annulée !</target> <target>Erreur d'enregistrement du mot de passe de l'utilisateur</target> <note>No comment provided by engineer.</note> </trans-unit> + <trans-unit id="Error scanning code: %@" xml:space="preserve"> + <source>Error scanning code: %@</source> + <target>Erreur lors du scan du code : %@</target> + <note>No comment provided by engineer.</note> + </trans-unit> <trans-unit id="Error sending email" xml:space="preserve"> <source>Error sending email</source> <target>Erreur lors de l'envoi de l'e-mail</target> @@ -2420,7 +2481,7 @@ Cette opération ne peut être annulée !</target> </trans-unit> <trans-unit id="Exit without saving" xml:space="preserve"> <source>Exit without saving</source> - <target>Quitter sans sauvegarder</target> + <target>Quitter sans enregistrer</target> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="Expand" xml:space="preserve"> @@ -2520,7 +2581,7 @@ Cette opération ne peut être annulée !</target> </trans-unit> <trans-unit id="Find chats faster" xml:space="preserve"> <source>Find chats faster</source> - <target>Trouver des messages plus rapidement</target> + <target>Recherche de message plus rapide</target> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="Fix" xml:space="preserve"> @@ -2663,9 +2724,9 @@ Cette opération ne peut être annulée !</target> <target>Les membres du groupe peuvent ajouter des réactions aux messages.</target> <note>No comment provided by engineer.</note> </trans-unit> - <trans-unit id="Group members can irreversibly delete sent messages." xml:space="preserve"> - <source>Group members can irreversibly delete sent messages.</source> - <target>Les membres du groupe peuvent supprimer de manière irréversible les messages envoyés.</target> + <trans-unit id="Group members can irreversibly delete sent messages. (24 hours)" xml:space="preserve"> + <source>Group members can irreversibly delete sent messages. (24 hours)</source> + <target>Les membres du groupe peuvent supprimer de manière irréversible les messages envoyés. (24 heures)</target> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="Group members can send direct messages." xml:space="preserve"> @@ -2773,6 +2834,11 @@ Cette opération ne peut être annulée !</target> <target>Historique</target> <note>No comment provided by engineer.</note> </trans-unit> + <trans-unit id="History is not sent to new members." xml:space="preserve"> + <source>History is not sent to new members.</source> + <target>L'historique n'est pas envoyé aux nouveaux membres.</target> + <note>No comment provided by engineer.</note> + </trans-unit> <trans-unit id="How SimpleX works" xml:space="preserve"> <source>How SimpleX works</source> <target>Comment SimpleX fonctionne</target> @@ -2808,11 +2874,6 @@ Cette opération ne peut être annulée !</target> <target>Si vous ne pouvez pas vous rencontrer en personne, montrez le code QR lors d'un appel vidéo ou partagez le lien.</target> <note>No comment provided by engineer.</note> </trans-unit> - <trans-unit id="If you cannot meet in person, you can **scan QR code in the video call**, or your contact can share an invitation link." xml:space="preserve"> - <source>If you cannot meet in person, you can **scan QR code in the video call**, or your contact can share an invitation link.</source> - <target>Si vous ne pouvez pas voir la personne, vous pouvez **scanner le code QR dans un appel vidéo**, ou votre contact peut vous partager un lien d'invitation.</target> - <note>No comment provided by engineer.</note> - </trans-unit> <trans-unit id="If you enter this passcode when opening the app, all app data will be irreversibly removed!" xml:space="preserve"> <source>If you enter this passcode when opening the app, all app data will be irreversibly removed!</source> <target>Si vous saisissez ce code à l'ouverture de l'application, toutes les données de l'application seront irréversiblement supprimées !</target> @@ -2868,6 +2929,11 @@ Cette opération ne peut être annulée !</target> <target>Importer la base de données</target> <note>No comment provided by engineer.</note> </trans-unit> + <trans-unit id="Improved message delivery" xml:space="preserve"> + <source>Improved message delivery</source> + <target>Amélioration de la transmission des messages</target> + <note>No comment provided by engineer.</note> + </trans-unit> <trans-unit id="Improved privacy and security" xml:space="preserve"> <source>Improved privacy and security</source> <target>Une meilleure sécurité et protection de la vie privée</target> @@ -2970,16 +3036,36 @@ Cette opération ne peut être annulée !</target> <target>Interface</target> <note>No comment provided by engineer.</note> </trans-unit> + <trans-unit id="Invalid QR code" xml:space="preserve"> + <source>Invalid QR code</source> + <target>Code QR invalide</target> + <note>No comment provided by engineer.</note> + </trans-unit> <trans-unit id="Invalid connection link" xml:space="preserve"> <source>Invalid connection link</source> <target>Lien de connection invalide</target> <note>No comment provided by engineer.</note> </trans-unit> + <trans-unit id="Invalid display name!" xml:space="preserve"> + <source>Invalid display name!</source> + <target>Nom d'affichage invalide !</target> + <note>No comment provided by engineer.</note> + </trans-unit> + <trans-unit id="Invalid link" xml:space="preserve"> + <source>Invalid link</source> + <target>Lien invalide</target> + <note>No comment provided by engineer.</note> + </trans-unit> <trans-unit id="Invalid name!" xml:space="preserve"> <source>Invalid name!</source> <target>Nom invalide !</target> <note>No comment provided by engineer.</note> </trans-unit> + <trans-unit id="Invalid response" xml:space="preserve"> + <source>Invalid response</source> + <target>Réponse invalide</target> + <note>No comment provided by engineer.</note> + </trans-unit> <trans-unit id="Invalid server address!" xml:space="preserve"> <source>Invalid server address!</source> <target>Adresse de serveur invalide !</target> @@ -3071,6 +3157,11 @@ Cette opération ne peut être annulée !</target> <target>Rejoindre le groupe</target> <note>No comment provided by engineer.</note> </trans-unit> + <trans-unit id="Join group conversations" xml:space="preserve"> + <source>Join group conversations</source> + <target>Participez aux conversations de groupe</target> + <note>No comment provided by engineer.</note> + </trans-unit> <trans-unit id="Join group?" xml:space="preserve"> <source>Join group?</source> <target>Rejoindre le groupe ?</target> @@ -3098,11 +3189,21 @@ Voici votre lien pour le groupe %@ !</target> <target>Entrain de rejoindre le groupe</target> <note>No comment provided by engineer.</note> </trans-unit> + <trans-unit id="Keep" xml:space="preserve"> + <source>Keep</source> + <target>Conserver</target> + <note>No comment provided by engineer.</note> + </trans-unit> <trans-unit id="Keep the app open to use it from desktop" xml:space="preserve"> <source>Keep the app open to use it from desktop</source> <target>Garder l'application ouverte pour l'utiliser depuis le bureau</target> <note>No comment provided by engineer.</note> </trans-unit> + <trans-unit id="Keep unused invitation?" xml:space="preserve"> + <source>Keep unused invitation?</source> + <target>Conserver l'invitation inutilisée ?</target> + <note>No comment provided by engineer.</note> + </trans-unit> <trans-unit id="Keep your connections" xml:space="preserve"> <source>Keep your connections</source> <target>Conserver vos connexions</target> @@ -3188,6 +3289,11 @@ Voici votre lien pour le groupe %@ !</target> <target>Messages dynamiques</target> <note>No comment provided by engineer.</note> </trans-unit> + <trans-unit id="Local" xml:space="preserve"> + <source>Local</source> + <target>Local</target> + <note>No comment provided by engineer.</note> + </trans-unit> <trans-unit id="Local name" xml:space="preserve"> <source>Local name</source> <target>Nom local</target> @@ -3428,6 +3534,11 @@ Voici votre lien pour le groupe %@ !</target> <target>Nouveau code d'accès</target> <note>No comment provided by engineer.</note> </trans-unit> + <trans-unit id="New chat" xml:space="preserve"> + <source>New chat</source> + <target>Nouveau chat</target> + <note>No comment provided by engineer.</note> + </trans-unit> <trans-unit id="New contact request" xml:space="preserve"> <source>New contact request</source> <target>Nouvelle demande de contact</target> @@ -3505,7 +3616,7 @@ Voici votre lien pour le groupe %@ !</target> </trans-unit> <trans-unit id="No filtered chats" xml:space="preserve"> <source>No filtered chats</source> - <target>Pas de chats filtrés</target> + <target>Aucune discussion filtrés</target> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="No group!" xml:space="preserve"> @@ -3552,16 +3663,16 @@ Voici votre lien pour le groupe %@ !</target> - désactiver des membres (rôle "observateur")</target> <note>No comment provided by engineer.</note> </trans-unit> + <trans-unit id="OK" xml:space="preserve"> + <source>OK</source> + <target>OK</target> + <note>No comment provided by engineer.</note> + </trans-unit> <trans-unit id="Off" xml:space="preserve"> <source>Off</source> <target>Off</target> <note>No comment provided by engineer.</note> </trans-unit> - <trans-unit id="Off (Local)" xml:space="preserve"> - <source>Off (Local)</source> - <target>Off (Local)</target> - <note>No comment provided by engineer.</note> - </trans-unit> <trans-unit id="Ok" xml:space="preserve"> <source>Ok</source> <target>Ok</target> @@ -3622,9 +3733,9 @@ Voici votre lien pour le groupe %@ !</target> <target>Vous seul pouvez ajouter des réactions aux messages.</target> <note>No comment provided by engineer.</note> </trans-unit> - <trans-unit id="Only you can irreversibly delete messages (your contact can mark them for deletion)." xml:space="preserve"> - <source>Only you can irreversibly delete messages (your contact can mark them for deletion).</source> - <target>Vous êtes le seul à pouvoir supprimer des messages de manière irréversible (votre contact peut les marquer comme supprimé).</target> + <trans-unit id="Only you can irreversibly delete messages (your contact can mark them for deletion). (24 hours)" xml:space="preserve"> + <source>Only you can irreversibly delete messages (your contact can mark them for deletion). (24 hours)</source> + <target>Vous êtes le seul à pouvoir supprimer des messages de manière irréversible (votre contact peut les marquer comme supprimé). (24 heures)</target> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="Only you can make calls." xml:space="preserve"> @@ -3647,9 +3758,9 @@ Voici votre lien pour le groupe %@ !</target> <target>Seul votre contact peut ajouter des réactions aux messages.</target> <note>No comment provided by engineer.</note> </trans-unit> - <trans-unit id="Only your contact can irreversibly delete messages (you can mark them for deletion)." xml:space="preserve"> - <source>Only your contact can irreversibly delete messages (you can mark them for deletion).</source> - <target>Seul votre contact peut supprimer de manière irréversible des messages (vous pouvez les marquer comme supprimé).</target> + <trans-unit id="Only your contact can irreversibly delete messages (you can mark them for deletion). (24 hours)" xml:space="preserve"> + <source>Only your contact can irreversibly delete messages (you can mark them for deletion). (24 hours)</source> + <target>Seul votre contact peut supprimer de manière irréversible des messages (vous pouvez les marquer comme supprimé). (24 heures)</target> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="Only your contact can make calls." xml:space="preserve"> @@ -3702,9 +3813,19 @@ Voici votre lien pour le groupe %@ !</target> <target>Protocole et code open-source – n'importe qui peut heberger un serveur.</target> <note>No comment provided by engineer.</note> </trans-unit> - <trans-unit id="Opening database…" xml:space="preserve"> - <source>Opening database…</source> - <target>Ouverture de la base de données…</target> + <trans-unit id="Opening app…" xml:space="preserve"> + <source>Opening app…</source> + <target>Ouverture de l'app…</target> + <note>No comment provided by engineer.</note> + </trans-unit> + <trans-unit id="Or scan QR code" xml:space="preserve"> + <source>Or scan QR code</source> + <target>Ou scanner le code QR</target> + <note>No comment provided by engineer.</note> + </trans-unit> + <trans-unit id="Or show this code" xml:space="preserve"> + <source>Or show this code</source> + <target>Ou présenter ce code</target> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="PING count" xml:space="preserve"> @@ -3747,10 +3868,10 @@ Voici votre lien pour le groupe %@ !</target> <target>Mot de passe à entrer</target> <note>No comment provided by engineer.</note> </trans-unit> - <trans-unit id="Paste" xml:space="preserve"> - <source>Paste</source> - <target>Coller</target> - <note>No comment provided by engineer.</note> + <trans-unit id="Past member %@" xml:space="preserve"> + <source>Past member %@</source> + <target>Ancien membre %@</target> + <note>past/unknown group member</note> </trans-unit> <trans-unit id="Paste desktop address" xml:space="preserve"> <source>Paste desktop address</source> @@ -3762,15 +3883,15 @@ Voici votre lien pour le groupe %@ !</target> <target>Coller l'image</target> <note>No comment provided by engineer.</note> </trans-unit> - <trans-unit id="Paste received link" xml:space="preserve"> - <source>Paste received link</source> - <target>Coller le lien reçu</target> + <trans-unit id="Paste link to connect!" xml:space="preserve"> + <source>Paste link to connect!</source> + <target>Collez le lien pour vous connecter !</target> <note>No comment provided by engineer.</note> </trans-unit> - <trans-unit id="Paste the link you received to connect with your contact." xml:space="preserve"> - <source>Paste the link you received to connect with your contact.</source> - <target>Collez le lien que vous avez reçu dans le cadre ci-dessous pour vous connecter avec votre contact.</target> - <note>placeholder</note> + <trans-unit id="Paste the link you received" xml:space="preserve"> + <source>Paste the link you received</source> + <target>Collez le lien que vous avez reçu</target> + <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="People can connect to you only via the links you share." xml:space="preserve"> <source>People can connect to you only via the links you share.</source> @@ -3807,6 +3928,13 @@ Voici votre lien pour le groupe %@ !</target> <target>Veuillez vérifier vos préférences ainsi que celles de votre contact.</target> <note>No comment provided by engineer.</note> </trans-unit> + <trans-unit id="Please contact developers. Error: %@" xml:space="preserve"> + <source>Please contact developers. +Error: %@</source> + <target>Veuillez contacter les développeurs. +Erreur : %@</target> + <note>No comment provided by engineer.</note> + </trans-unit> <trans-unit id="Please contact group admin." xml:space="preserve"> <source>Please contact group admin.</source> <target>Veuillez contacter l'administrateur du groupe.</target> @@ -3892,6 +4020,11 @@ Voici votre lien pour le groupe %@ !</target> <target>Noms de fichiers privés</target> <note>No comment provided by engineer.</note> </trans-unit> + <trans-unit id="Private notes" xml:space="preserve"> + <source>Private notes</source> + <target>Notes privées</target> + <note>name of notes to self</note> + </trans-unit> <trans-unit id="Profile and server connections" xml:space="preserve"> <source>Profile and server connections</source> <target>Profil et connexions au serveur</target> @@ -4012,6 +4145,11 @@ Voici votre lien pour le groupe %@ !</target> <target>Pour en savoir plus, consultez le [Guide de l'utilisateur](https://simplex.chat/docs/guide/app-settings.html#your-simplex-contact-address).</target> <note>No comment provided by engineer.</note> </trans-unit> + <trans-unit id="Read more in [User Guide](https://simplex.chat/docs/guide/chat-profiles.html#incognito-mode)." xml:space="preserve"> + <source>Read more in [User Guide](https://simplex.chat/docs/guide/chat-profiles.html#incognito-mode).</source> + <target>Pour en savoir plus, consultez le [Guide de l'utilisateur](https ://simplex.chat/docs/guide/chat-profiles.html#incognito-mode).</target> + <note>No comment provided by engineer.</note> + </trans-unit> <trans-unit id="Read more in [User Guide](https://simplex.chat/docs/guide/readme.html#connect-to-friends)." xml:space="preserve"> <source>Read more in [User Guide](https://simplex.chat/docs/guide/readme.html#connect-to-friends).</source> <target>Pour en savoir plus, consultez le [Guide de l'utilisateur](https://simplex.chat/docs/guide/readme.html#connect-to-friends).</target> @@ -4067,6 +4205,11 @@ Voici votre lien pour le groupe %@ !</target> <target>Réception via</target> <note>No comment provided by engineer.</note> </trans-unit> + <trans-unit id="Recent history and improved [directory bot](simplex:/contact#/?v=1-4&smp=smp%3A%2F%2Fu2dS9sG8nMNURyZwqASV4yROM28Er0luVTx5X1CsMrU%3D%40smp4.simplex.im%2FeXSPwqTkKyDO3px4fLf1wx3MvPdjdLW3%23%2F%3Fv%3D1-2%26dh%3DMCowBQYDK2VuAyEAaiv6MkMH44L2TcYrt_CsX3ZvM11WgbMEUn0hkIKTOho%253D%26srv%3Do5vmywmrnaxalvz6wi3zicyftgio6psuvyniis6gco6bp6ekl4cqj4id.onion)." xml:space="preserve"> + <source>Recent history and improved [directory bot](simplex:/contact#/?v=1-4&smp=smp%3A%2F%2Fu2dS9sG8nMNURyZwqASV4yROM28Er0luVTx5X1CsMrU%3D%40smp4.simplex.im%2FeXSPwqTkKyDO3px4fLf1wx3MvPdjdLW3%23%2F%3Fv%3D1-2%26dh%3DMCowBQYDK2VuAyEAaiv6MkMH44L2TcYrt_CsX3ZvM11WgbMEUn0hkIKTOho%253D%26srv%3Do5vmywmrnaxalvz6wi3zicyftgio6psuvyniis6gco6bp6ekl4cqj4id.onion).</source> + <target>Historique récent et amélioration du [bot annuaire](simplex:/contact#/?v=1-4&smp=smp%3A%2F%2Fu2dS9sG8nMNURyZwqASV4yROM28Er0luVTx5X1CsMrU%3D%40smp4.simplex.im%2FeXSPwqTkKyDO3px4fLf1wx3MvPdjdLW3%23%2F%3Fv%3D1-2%26dh%3DMCowBQYDK2VuAyEAaiv6MkMH44L2TcYrt_CsX3ZvM11WgbMEUn0hkIKTOho%253D%26srv%3Do5vmywmrnaxalvz6wi3zicyftgio6psuvyniis6gco6bp6ekl4cqj4id.onion).</target> + <note>No comment provided by engineer.</note> + </trans-unit> <trans-unit id="Recipients see updates as you type them." xml:space="preserve"> <source>Recipients see updates as you type them.</source> <target>Les destinataires voient les mises à jour au fur et à mesure que vous leur écrivez.</target> @@ -4222,6 +4365,11 @@ Voici votre lien pour le groupe %@ !</target> <target>Erreur de restauration de la base de données</target> <note>No comment provided by engineer.</note> </trans-unit> + <trans-unit id="Retry" xml:space="preserve"> + <source>Retry</source> + <target>Réessayer</target> + <note>No comment provided by engineer.</note> + </trans-unit> <trans-unit id="Reveal" xml:space="preserve"> <source>Reveal</source> <target>Révéler</target> @@ -4264,57 +4412,57 @@ Voici votre lien pour le groupe %@ !</target> </trans-unit> <trans-unit id="Save" xml:space="preserve"> <source>Save</source> - <target>Sauvegarder</target> + <target>Enregistrer</target> <note>chat item action</note> </trans-unit> <trans-unit id="Save (and notify contacts)" xml:space="preserve"> <source>Save (and notify contacts)</source> - <target>Sauvegarder (et en informer les contacts)</target> + <target>Enregistrer (et en informer les contacts)</target> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="Save and notify contact" xml:space="preserve"> <source>Save and notify contact</source> - <target>Sauvegarder et en informer les contacts</target> + <target>Enregistrer et en informer le contact</target> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="Save and notify group members" xml:space="preserve"> <source>Save and notify group members</source> - <target>Sauvegarder et en informer les membres du groupe</target> + <target>Enregistrer et en informer les membres du groupe</target> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="Save and update group profile" xml:space="preserve"> <source>Save and update group profile</source> - <target>Sauvegarder et mettre à jour le profil du groupe</target> + <target>Enregistrer et mettre à jour le profil du groupe</target> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="Save archive" xml:space="preserve"> <source>Save archive</source> - <target>Sauvegarder l'archive</target> + <target>Enregistrer l'archive</target> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="Save auto-accept settings" xml:space="preserve"> <source>Save auto-accept settings</source> - <target>Sauvegarder les paramètres d'acceptation automatique</target> + <target>Enregistrer les paramètres de validation automatique</target> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="Save group profile" xml:space="preserve"> <source>Save group profile</source> - <target>Sauvegarder le profil du groupe</target> + <target>Enregistrer le profil du groupe</target> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="Save passphrase and open chat" xml:space="preserve"> <source>Save passphrase and open chat</source> - <target>Sauvegarder la phrase secrète et ouvrir le chat</target> + <target>Enregistrer la phrase secrète et ouvrir le chat</target> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="Save passphrase in Keychain" xml:space="preserve"> <source>Save passphrase in Keychain</source> - <target>Sauvegarder la phrase secrète dans la keychain</target> + <target>Enregistrer la phrase secrète dans la Keychain</target> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="Save preferences?" xml:space="preserve"> <source>Save preferences?</source> - <target>Sauvegarder les préférences ?</target> + <target>Enregistrer les préférences ?</target> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="Save profile password" xml:space="preserve"> @@ -4324,22 +4472,22 @@ Voici votre lien pour le groupe %@ !</target> </trans-unit> <trans-unit id="Save servers" xml:space="preserve"> <source>Save servers</source> - <target>Sauvegarder les serveurs</target> + <target>Enregistrer les serveurs</target> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="Save servers?" xml:space="preserve"> <source>Save servers?</source> - <target>Sauvegarder les serveurs ?</target> + <target>Enregistrer les serveurs ?</target> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="Save settings?" xml:space="preserve"> <source>Save settings?</source> - <target>Sauvegarder les paramètres ?</target> + <target>Enregistrer les paramètres ?</target> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="Save welcome message?" xml:space="preserve"> <source>Save welcome message?</source> - <target>Sauvegarder le message d'accueil ?</target> + <target>Enregistrer le message d'accueil ?</target> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="Saved WebRTC ICE servers will be removed" xml:space="preserve"> @@ -4347,6 +4495,11 @@ Voici votre lien pour le groupe %@ !</target> <target>Les serveurs WebRTC ICE sauvegardés seront supprimés</target> <note>No comment provided by engineer.</note> </trans-unit> + <trans-unit id="Saved message" xml:space="preserve"> + <source>Saved message</source> + <target>Message enregistré</target> + <note>message info title</note> + </trans-unit> <trans-unit id="Scan QR code" xml:space="preserve"> <source>Scan QR code</source> <target>Scanner un code QR</target> @@ -4354,7 +4507,7 @@ Voici votre lien pour le groupe %@ !</target> </trans-unit> <trans-unit id="Scan QR code from desktop" xml:space="preserve"> <source>Scan QR code from desktop</source> - <target>Scanner le code QR du bureau</target> + <target>Scannez le code QR du bureau</target> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="Scan code" xml:space="preserve"> @@ -4374,7 +4527,17 @@ Voici votre lien pour le groupe %@ !</target> </trans-unit> <trans-unit id="Search" xml:space="preserve"> <source>Search</source> - <target>Recherche</target> + <target>Rechercher</target> + <note>No comment provided by engineer.</note> + </trans-unit> + <trans-unit id="Search bar accepts invitation links." xml:space="preserve"> + <source>Search bar accepts invitation links.</source> + <target>La barre de recherche accepte les liens d'invitation.</target> + <note>No comment provided by engineer.</note> + </trans-unit> + <trans-unit id="Search or paste SimpleX link" xml:space="preserve"> + <source>Search or paste SimpleX link</source> + <target>Rechercher ou coller un lien SimpleX</target> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="Secure queue" xml:space="preserve"> @@ -4474,7 +4637,7 @@ Voici votre lien pour le groupe %@ !</target> </trans-unit> <trans-unit id="Send receipts" xml:space="preserve"> <source>Send receipts</source> - <target>Envoyer les justificatifs</target> + <target>Envoi de justificatifs</target> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="Send them from gallery or custom keyboards." xml:space="preserve"> @@ -4482,6 +4645,11 @@ Voici votre lien pour le groupe %@ !</target> <target>Envoyez-les depuis la phototèque ou des claviers personnalisés.</target> <note>No comment provided by engineer.</note> </trans-unit> + <trans-unit id="Send up to 100 last messages to new members." xml:space="preserve"> + <source>Send up to 100 last messages to new members.</source> + <target>Envoi des 100 derniers messages aux nouveaux membres.</target> + <note>No comment provided by engineer.</note> + </trans-unit> <trans-unit id="Sender cancelled file transfer." xml:space="preserve"> <source>Sender cancelled file transfer.</source> <target>L'expéditeur a annulé le transfert de fichiers.</target> @@ -4652,9 +4820,9 @@ Voici votre lien pour le groupe %@ !</target> <target>Partager le lien</target> <note>No comment provided by engineer.</note> </trans-unit> - <trans-unit id="Share one-time invitation link" xml:space="preserve"> - <source>Share one-time invitation link</source> - <target>Partager un lien d'invitation unique</target> + <trans-unit id="Share this 1-time invite link" xml:space="preserve"> + <source>Share this 1-time invite link</source> + <target>Partager ce lien d'invitation unique</target> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="Share with contacts" xml:space="preserve"> @@ -4777,16 +4945,16 @@ Voici votre lien pour le groupe %@ !</target> <target>Quelqu'un</target> <note>notification title</note> </trans-unit> - <trans-unit id="Start a new chat" xml:space="preserve"> - <source>Start a new chat</source> - <target>Commencer une nouvelle conversation</target> - <note>No comment provided by engineer.</note> - </trans-unit> <trans-unit id="Start chat" xml:space="preserve"> <source>Start chat</source> <target>Démarrer le chat</target> <note>No comment provided by engineer.</note> </trans-unit> + <trans-unit id="Start chat?" xml:space="preserve"> + <source>Start chat?</source> + <target>Lancer le chat ?</target> + <note>No comment provided by engineer.</note> + </trans-unit> <trans-unit id="Start migration" xml:space="preserve"> <source>Start migration</source> <target>Démarrer la migration</target> @@ -4912,6 +5080,16 @@ Voici votre lien pour le groupe %@ !</target> <target>Appuyez pour rejoindre incognito</target> <note>No comment provided by engineer.</note> </trans-unit> + <trans-unit id="Tap to paste link" xml:space="preserve"> + <source>Tap to paste link</source> + <target>Appuyez pour coller le lien</target> + <note>No comment provided by engineer.</note> + </trans-unit> + <trans-unit id="Tap to scan" xml:space="preserve"> + <source>Tap to scan</source> + <target>Appuyez pour scanner</target> + <note>No comment provided by engineer.</note> + </trans-unit> <trans-unit id="Tap to start a new chat" xml:space="preserve"> <source>Tap to start a new chat</source> <target>Appuyez ici pour démarrer une nouvelle discussion</target> @@ -4974,6 +5152,11 @@ Cela peut se produire en raison d'un bug ou lorsque la connexion est compromise. <target>La tentative de modification de la phrase secrète de la base de données n'a pas abouti.</target> <note>No comment provided by engineer.</note> </trans-unit> + <trans-unit id="The code you scanned is not a SimpleX link QR code." xml:space="preserve"> + <source>The code you scanned is not a SimpleX link QR code.</source> + <target>Le code scanné n'est pas un code QR de lien SimpleX.</target> + <note>No comment provided by engineer.</note> + </trans-unit> <trans-unit id="The connection you accepted will be cancelled!" xml:space="preserve"> <source>The connection you accepted will be cancelled!</source> <target>La connexion que vous avez acceptée sera annulée !</target> @@ -5039,21 +5222,16 @@ Cela peut se produire en raison d'un bug ou lorsque la connexion est compromise. <target>Les serveurs pour les nouvelles connexions de votre profil de chat actuel **%@**.</target> <note>No comment provided by engineer.</note> </trans-unit> + <trans-unit id="The text you pasted is not a SimpleX link." xml:space="preserve"> + <source>The text you pasted is not a SimpleX link.</source> + <target>Le texte collé n'est pas un lien SimpleX.</target> + <note>No comment provided by engineer.</note> + </trans-unit> <trans-unit id="Theme" xml:space="preserve"> <source>Theme</source> <target>Thème</target> <note>No comment provided by engineer.</note> </trans-unit> - <trans-unit id="There should be at least one user profile." xml:space="preserve"> - <source>There should be at least one user profile.</source> - <target>Il doit y avoir au moins un profil d'utilisateur.</target> - <note>No comment provided by engineer.</note> - </trans-unit> - <trans-unit id="There should be at least one visible user profile." xml:space="preserve"> - <source>There should be at least one visible user profile.</source> - <target>Il doit y avoir au moins un profil d'utilisateur visible.</target> - <note>No comment provided by engineer.</note> - </trans-unit> <trans-unit id="These settings are for your current profile **%@**." xml:space="preserve"> <source>These settings are for your current profile **%@**.</source> <target>Ces paramètres s'appliquent à votre profil actuel **%@**.</target> @@ -5081,7 +5259,12 @@ Cela peut se produire en raison d'un bug ou lorsque la connexion est compromise. </trans-unit> <trans-unit id="This device name" xml:space="preserve"> <source>This device name</source> - <target>Ce nom d'appareil</target> + <target>Nom de cet appareil</target> + <note>No comment provided by engineer.</note> + </trans-unit> + <trans-unit id="This display name is invalid. Please choose another name." xml:space="preserve"> + <source>This display name is invalid. Please choose another name.</source> + <target>Ce nom d'affichage est invalide. Veuillez choisir un autre nom.</target> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="This group has over %lld members, delivery receipts are not sent." xml:space="preserve"> @@ -5186,16 +5369,16 @@ Vous serez invité à confirmer l'authentification avant que cette fonction ne s <target>Tentative de connexion au serveur utilisé pour recevoir les messages de ce contact.</target> <note>No comment provided by engineer.</note> </trans-unit> + <trans-unit id="Turkish interface" xml:space="preserve"> + <source>Turkish interface</source> + <target>Interface en turc</target> + <note>No comment provided by engineer.</note> + </trans-unit> <trans-unit id="Turn off" xml:space="preserve"> <source>Turn off</source> <target>Désactiver</target> <note>No comment provided by engineer.</note> </trans-unit> - <trans-unit id="Turn off notifications?" xml:space="preserve"> - <source>Turn off notifications?</source> - <target>Désactiver les notifications ?</target> - <note>No comment provided by engineer.</note> - </trans-unit> <trans-unit id="Turn on" xml:space="preserve"> <source>Turn on</source> <target>Activer</target> @@ -5211,11 +5394,19 @@ Vous serez invité à confirmer l'authentification avant que cette fonction ne s <target>Débloquer</target> <note>No comment provided by engineer.</note> </trans-unit> + <trans-unit id="Unblock for all" xml:space="preserve"> + <source>Unblock for all</source> + <note>No comment provided by engineer.</note> + </trans-unit> <trans-unit id="Unblock member" xml:space="preserve"> <source>Unblock member</source> <target>Débloquer ce membre</target> <note>No comment provided by engineer.</note> </trans-unit> + <trans-unit id="Unblock member for all?" xml:space="preserve"> + <source>Unblock member for all?</source> + <note>No comment provided by engineer.</note> + </trans-unit> <trans-unit id="Unblock member?" xml:space="preserve"> <source>Unblock member?</source> <target>Débloquer ce membre ?</target> @@ -5313,6 +5504,11 @@ Pour vous connecter, veuillez demander à votre contact de créer un autre lien <target>Non lu</target> <note>No comment provided by engineer.</note> </trans-unit> + <trans-unit id="Up to 100 last messages are sent to new members." xml:space="preserve"> + <source>Up to 100 last messages are sent to new members.</source> + <target>Les 100 derniers messages sont envoyés aux nouveaux membres.</target> + <note>No comment provided by engineer.</note> + </trans-unit> <trans-unit id="Update" xml:space="preserve"> <source>Update</source> <target>Mise à jour</target> @@ -5385,7 +5581,7 @@ Pour vous connecter, veuillez demander à votre contact de créer un autre lien </trans-unit> <trans-unit id="Use from desktop" xml:space="preserve"> <source>Use from desktop</source> - <target>Utilisation depuis le bureau</target> + <target>Accès au bureau</target> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="Use iOS call interface" xml:space="preserve"> @@ -5398,6 +5594,11 @@ Pour vous connecter, veuillez demander à votre contact de créer un autre lien <target>Utiliser un nouveau profil incognito</target> <note>No comment provided by engineer.</note> </trans-unit> + <trans-unit id="Use only local notifications?" xml:space="preserve"> + <source>Use only local notifications?</source> + <target>Utilisation de notifications locales uniquement ?</target> + <note>No comment provided by engineer.</note> + </trans-unit> <trans-unit id="Use server" xml:space="preserve"> <source>Use server</source> <target>Utiliser ce serveur</target> @@ -5478,6 +5679,11 @@ Pour vous connecter, veuillez demander à votre contact de créer un autre lien <target>Afficher le code de sécurité</target> <note>No comment provided by engineer.</note> </trans-unit> + <trans-unit id="Visible history" xml:space="preserve"> + <source>Visible history</source> + <target>Historique visible</target> + <note>chat feature</note> + </trans-unit> <trans-unit id="Voice messages" xml:space="preserve"> <source>Voice messages</source> <target>Messages vocaux</target> @@ -5563,11 +5769,21 @@ Pour vous connecter, veuillez demander à votre contact de créer un autre lien <target>Lorsque vous partagez un profil incognito avec quelqu'un, ce profil sera utilisé pour les groupes auxquels il vous invite.</target> <note>No comment provided by engineer.</note> </trans-unit> + <trans-unit id="With encrypted files and media." xml:space="preserve"> + <source>With encrypted files and media.</source> + <target>Avec les fichiers et les médias chiffrés.</target> + <note>No comment provided by engineer.</note> + </trans-unit> <trans-unit id="With optional welcome message." xml:space="preserve"> <source>With optional welcome message.</source> <target>Avec message de bienvenue facultatif.</target> <note>No comment provided by engineer.</note> </trans-unit> + <trans-unit id="With reduced battery usage." xml:space="preserve"> + <source>With reduced battery usage.</source> + <target>Consommation réduite de la batterie.</target> + <note>No comment provided by engineer.</note> + </trans-unit> <trans-unit id="Wrong database passphrase" xml:space="preserve"> <source>Wrong database passphrase</source> <target>Mauvaise phrase secrète pour la base de données</target> @@ -5660,11 +5876,6 @@ Répéter la demande d'adhésion ?</target> <target>Vous pouvez accepter des appels à partir de l'écran de verrouillage, sans authentification de l'appareil ou de l'application.</target> <note>No comment provided by engineer.</note> </trans-unit> - <trans-unit id="You can also connect by clicking the link. If it opens in the browser, click **Open in mobile app** button." xml:space="preserve"> - <source>You can also connect by clicking the link. If it opens in the browser, click **Open in mobile app** button.</source> - <target>Vous pouvez également vous connecter en cliquant sur le lien. S'il s'ouvre dans le navigateur, cliquez sur le bouton **Open in mobile app**.</target> - <note>No comment provided by engineer.</note> - </trans-unit> <trans-unit id="You can create it later" xml:space="preserve"> <source>You can create it later</source> <target>Vous pouvez la créer plus tard</target> @@ -5685,6 +5896,11 @@ Répéter la demande d'adhésion ?</target> <target>Vous pouvez masquer ou mettre en sourdine un profil d'utilisateur - faites-le glisser vers la droite.</target> <note>No comment provided by engineer.</note> </trans-unit> + <trans-unit id="You can make it visible to your SimpleX contacts via Settings." xml:space="preserve"> + <source>You can make it visible to your SimpleX contacts via Settings.</source> + <target>Vous pouvez le rendre visible à vos contacts SimpleX via Paramètres.</target> + <note>No comment provided by engineer.</note> + </trans-unit> <trans-unit id="You can now send messages to %@" xml:space="preserve"> <source>You can now send messages to %@</source> <target>Vous pouvez maintenant envoyer des messages à %@</target> @@ -5725,6 +5941,11 @@ Répéter la demande d'adhésion ?</target> <target>Vous pouvez utiliser le format markdown pour mettre en forme les messages :</target> <note>No comment provided by engineer.</note> </trans-unit> + <trans-unit id="You can view invitation link again in connection details." xml:space="preserve"> + <source>You can view invitation link again in connection details.</source> + <target>Vous pouvez à nouveau consulter le lien d'invitation dans les détails de la connexion.</target> + <note>No comment provided by engineer.</note> + </trans-unit> <trans-unit id="You can't send messages!" xml:space="preserve"> <source>You can't send messages!</source> <target>Vous ne pouvez pas envoyer de messages !</target> @@ -5914,13 +6135,6 @@ Vous pouvez annuler la connexion et supprimer le contact (et réessayer plus tar <target>Vos contacts peuvent autoriser la suppression complète des messages.</target> <note>No comment provided by engineer.</note> </trans-unit> - <trans-unit id="Your contacts in SimpleX will see it. You can change it in Settings." xml:space="preserve"> - <source>Your contacts in SimpleX will see it. -You can change it in Settings.</source> - <target>Vos contacts dans SimpleX la verront. -Vous pouvez modifier ce choix dans les Paramètres.</target> - <note>No comment provided by engineer.</note> - </trans-unit> <trans-unit id="Your contacts will remain connected." xml:space="preserve"> <source>Your contacts will remain connected.</source> <target>Vos contacts resteront connectés.</target> @@ -6073,6 +6287,14 @@ Les serveurs SimpleX ne peuvent pas voir votre profil.</target> <target>blocké</target> <note>No comment provided by engineer.</note> </trans-unit> + <trans-unit id="blocked %@" xml:space="preserve"> + <source>blocked %@</source> + <note>rcv group event chat item</note> + </trans-unit> + <trans-unit id="blocked by admin" xml:space="preserve"> + <source>blocked by admin</source> + <note>blocked chat item</note> + </trans-unit> <trans-unit id="bold" xml:space="preserve"> <source>bold</source> <target>gras</target> @@ -6193,6 +6415,11 @@ Les serveurs SimpleX ne peuvent pas voir votre profil.</target> <target>connexion : %@</target> <note>connection information</note> </trans-unit> + <trans-unit id="contact %@ changed to %@" xml:space="preserve"> + <source>contact %1$@ changed to %2$@</source> + <target>le contact %1$@ est devenu %2$@</target> + <note>profile update event chat item</note> + </trans-unit> <trans-unit id="contact has e2e encryption" xml:space="preserve"> <source>contact has e2e encryption</source> <target>Ce contact a le chiffrement de bout en bout</target> @@ -6463,6 +6690,11 @@ Les serveurs SimpleX ne peuvent pas voir votre profil.</target> <target>membre</target> <note>member role</note> </trans-unit> + <trans-unit id="member %@ changed to %@" xml:space="preserve"> + <source>member %1$@ changed to %2$@</source> + <target>le membre %1$@ est devenu %2$@</target> + <note>profile update event chat item</note> + </trans-unit> <trans-unit id="member connected" xml:space="preserve"> <source>connected</source> <target>est connecté·e</target> @@ -6537,12 +6769,12 @@ Les serveurs SimpleX ne peuvent pas voir votre profil.</target> </trans-unit> <trans-unit id="offered %@" xml:space="preserve"> <source>offered %@</source> - <target>offert %@</target> + <target>propose %@</target> <note>feature offered item</note> </trans-unit> <trans-unit id="offered %@: %@" xml:space="preserve"> <source>offered %1$@: %2$@</source> - <target>offert %1$@ : %2$@</target> + <target>propose %1$@ : %2$@</target> <note>feature offered item</note> </trans-unit> <trans-unit id="on" xml:space="preserve"> @@ -6585,6 +6817,16 @@ Les serveurs SimpleX ne peuvent pas voir votre profil.</target> <target>a retiré %@</target> <note>rcv group event chat item</note> </trans-unit> + <trans-unit id="removed contact address" xml:space="preserve"> + <source>removed contact address</source> + <target>suppression de l'adresse de contact</target> + <note>profile update event chat item</note> + </trans-unit> + <trans-unit id="removed profile picture" xml:space="preserve"> + <source>removed profile picture</source> + <target>suppression de la photo de profil</target> + <note>profile update event chat item</note> + </trans-unit> <trans-unit id="removed you" xml:space="preserve"> <source>removed you</source> <target>vous a retiré</target> @@ -6615,6 +6857,16 @@ Les serveurs SimpleX ne peuvent pas voir votre profil.</target> <target>envoyer un message direct</target> <note>No comment provided by engineer.</note> </trans-unit> + <trans-unit id="set new contact address" xml:space="preserve"> + <source>set new contact address</source> + <target>définir une nouvelle adresse de contact</target> + <note>profile update event chat item</note> + </trans-unit> + <trans-unit id="set new profile picture" xml:space="preserve"> + <source>set new profile picture</source> + <target>définir une nouvelle image de profil</target> + <note>profile update event chat item</note> + </trans-unit> <trans-unit id="starting…" xml:space="preserve"> <source>starting…</source> <target>lancement…</target> @@ -6630,16 +6882,30 @@ Les serveurs SimpleX ne peuvent pas voir votre profil.</target> <target>ce contact</target> <note>notification title</note> </trans-unit> + <trans-unit id="unblocked %@" xml:space="preserve"> + <source>unblocked %@</source> + <note>rcv group event chat item</note> + </trans-unit> <trans-unit id="unknown" xml:space="preserve"> <source>unknown</source> <target>inconnu</target> <note>connection info</note> </trans-unit> + <trans-unit id="unknown status" xml:space="preserve"> + <source>unknown status</source> + <target>statut inconnu</target> + <note>No comment provided by engineer.</note> + </trans-unit> <trans-unit id="updated group profile" xml:space="preserve"> <source>updated group profile</source> <target>mise à jour du profil de groupe</target> <note>rcv group event chat item</note> </trans-unit> + <trans-unit id="updated profile" xml:space="preserve"> + <source>updated profile</source> + <target>profil mis à jour</target> + <note>profile update event chat item</note> + </trans-unit> <trans-unit id="v%@" xml:space="preserve"> <source>v%@</source> <target>v%@</target> @@ -6710,6 +6976,10 @@ Les serveurs SimpleX ne peuvent pas voir votre profil.</target> <target>vous êtes observateur</target> <note>No comment provided by engineer.</note> </trans-unit> + <trans-unit id="you blocked %@" xml:space="preserve"> + <source>you blocked %@</source> + <note>snd group event chat item</note> + </trans-unit> <trans-unit id="you changed address" xml:space="preserve"> <source>you changed address</source> <target>vous avez changé d'adresse</target> @@ -6750,6 +7020,10 @@ Les serveurs SimpleX ne peuvent pas voir votre profil.</target> <target>vous avez partagé un lien unique en incognito</target> <note>chat list item description</note> </trans-unit> + <trans-unit id="you unblocked %@" xml:space="preserve"> + <source>you unblocked %@</source> + <note>snd group event chat item</note> + </trans-unit> <trans-unit id="you: " xml:space="preserve"> <source>you: </source> <target>vous : </target> diff --git a/apps/ios/SimpleX Localizations/it.xcloc/Localized Contents/it.xliff b/apps/ios/SimpleX Localizations/it.xcloc/Localized Contents/it.xliff index bf1b1ee386..eff9291b3a 100644 --- a/apps/ios/SimpleX Localizations/it.xcloc/Localized Contents/it.xliff +++ b/apps/ios/SimpleX Localizations/it.xcloc/Localized Contents/it.xliff @@ -94,7 +94,7 @@ </trans-unit> <trans-unit id="%@ and %@ connected" xml:space="preserve"> <source>%@ and %@ connected</source> - <target>%@ e %@ sono connessi/e</target> + <target>%@ e %@ si sono connessi/e</target> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="%@ at %@:" xml:space="preserve"> @@ -139,7 +139,7 @@ </trans-unit> <trans-unit id="%@, %@ and %lld other members connected" xml:space="preserve"> <source>%@, %@ and %lld other members connected</source> - <target>%@, %@ e altri %lld membri sono connessi</target> + <target>%@, %@ e altri %lld membri si sono connessi</target> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="%@:" xml:space="preserve"> @@ -217,6 +217,11 @@ <target>%lld messaggi bloccati</target> <note>No comment provided by engineer.</note> </trans-unit> + <trans-unit id="%lld messages blocked by admin" xml:space="preserve"> + <source>%lld messages blocked by admin</source> + <target>%lld messaggi bloccati dall'amministratore</target> + <note>No comment provided by engineer.</note> + </trans-unit> <trans-unit id="%lld messages marked deleted" xml:space="preserve"> <source>%lld messages marked deleted</source> <target>%lld messaggi contrassegnati eliminati</target> @@ -312,14 +317,19 @@ <target>)</target> <note>No comment provided by engineer.</note> </trans-unit> + <trans-unit id="**Add contact**: to create a new invitation link, or connect via a link you received." xml:space="preserve"> + <source>**Add contact**: to create a new invitation link, or connect via a link you received.</source> + <target>**Aggiungi contatto**: per creare un nuovo link di invito o connetterti tramite un link che hai ricevuto.</target> + <note>No comment provided by engineer.</note> + </trans-unit> <trans-unit id="**Add new contact**: to create your one-time QR Code for your contact." xml:space="preserve"> <source>**Add new contact**: to create your one-time QR Code or link for your contact.</source> <target>**Aggiungi un contatto**: per creare il tuo codice QR o link una tantum per il tuo contatto.</target> <note>No comment provided by engineer.</note> </trans-unit> - <trans-unit id="**Create link / QR code** for your contact to use." xml:space="preserve"> - <source>**Create link / QR code** for your contact to use.</source> - <target>**Crea link / codice QR** da usare per il tuo contatto.</target> + <trans-unit id="**Create group**: to create a new group." xml:space="preserve"> + <source>**Create group**: to create a new group.</source> + <target>**Crea gruppo**: per creare un nuovo gruppo.</target> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="**More private**: check new messages every 20 minutes. Device token is shared with SimpleX Chat server, but not how many contacts or messages you have." xml:space="preserve"> @@ -332,11 +342,6 @@ <target>**Il più privato**: non usare il server di notifica di SimpleX Chat, controlla i messaggi periodicamente in secondo piano (dipende da quanto spesso usi l'app).</target> <note>No comment provided by engineer.</note> </trans-unit> - <trans-unit id="**Paste received link** or open it in the browser and tap **Open in mobile app**." xml:space="preserve"> - <source>**Paste received link** or open it in the browser and tap **Open in mobile app**.</source> - <target>**Incolla il link ricevuto** o aprilo nel browser e tocca **Apri in app mobile**.</target> - <note>No comment provided by engineer.</note> - </trans-unit> <trans-unit id="**Please note**: you will NOT be able to recover or change passphrase if you lose it." xml:space="preserve"> <source>**Please note**: you will NOT be able to recover or change passphrase if you lose it.</source> <target>**Nota bene**: NON potrai recuperare o cambiare la password se la perdi.</target> @@ -347,11 +352,6 @@ <target>**Consigliato**: vengono inviati il token del dispositivo e le notifiche al server di notifica di SimpleX Chat, ma non il contenuto del messaggio,la sua dimensione o il suo mittente.</target> <note>No comment provided by engineer.</note> </trans-unit> - <trans-unit id="**Scan QR code**: to connect to your contact in person or via video call." xml:space="preserve"> - <source>**Scan QR code**: to connect to your contact in person or via video call.</source> - <target>**Scansiona codice QR**: per connetterti al contatto di persona o via videochiamata.</target> - <note>No comment provided by engineer.</note> - </trans-unit> <trans-unit id="**Warning**: Instant push notifications require passphrase saved in Keychain." xml:space="preserve"> <source>**Warning**: Instant push notifications require passphrase saved in Keychain.</source> <target>**Attenzione**: le notifiche push istantanee richiedono una password salvata nel portachiavi.</target> @@ -453,11 +453,6 @@ <target>1 settimana</target> <note>time interval</note> </trans-unit> - <trans-unit id="1-time link" xml:space="preserve"> - <source>1-time link</source> - <target>Link una tantum</target> - <note>No comment provided by engineer.</note> - </trans-unit> <trans-unit id="5 minutes" xml:space="preserve"> <source>5 minutes</source> <target>5 minuti</target> @@ -573,6 +568,11 @@ <target>Aggiungi l'indirizzo al tuo profilo, in modo che i tuoi contatti possano condividerlo con altre persone. L'aggiornamento del profilo verrà inviato ai tuoi contatti.</target> <note>No comment provided by engineer.</note> </trans-unit> + <trans-unit id="Add contact" xml:space="preserve"> + <source>Add contact</source> + <target>Aggiungi contatto</target> + <note>No comment provided by engineer.</note> + </trans-unit> <trans-unit id="Add preset servers" xml:space="preserve"> <source>Add preset servers</source> <target>Aggiungi server preimpostati</target> @@ -643,6 +643,11 @@ <target>Tutti i membri del gruppo resteranno connessi.</target> <note>No comment provided by engineer.</note> </trans-unit> + <trans-unit id="All messages will be deleted - this cannot be undone!" xml:space="preserve"> + <source>All messages will be deleted - this cannot be undone!</source> + <target>Tutti i messaggi verranno eliminati, non è reversibile!</target> + <note>No comment provided by engineer.</note> + </trans-unit> <trans-unit id="All messages will be deleted - this cannot be undone! The messages will be deleted ONLY for you." xml:space="preserve"> <source>All messages will be deleted - this cannot be undone! The messages will be deleted ONLY for you.</source> <target>Tutti i messaggi verranno eliminati, non è reversibile! I messaggi verranno eliminati SOLO per te.</target> @@ -678,9 +683,9 @@ <target>Consenti i messaggi a tempo solo se il contatto li consente a te.</target> <note>No comment provided by engineer.</note> </trans-unit> - <trans-unit id="Allow irreversible message deletion only if your contact allows it to you." xml:space="preserve"> - <source>Allow irreversible message deletion only if your contact allows it to you.</source> - <target>Consenti l'eliminazione irreversibile dei messaggi solo se il contatto la consente a te.</target> + <trans-unit id="Allow irreversible message deletion only if your contact allows it to you. (24 hours)" xml:space="preserve"> + <source>Allow irreversible message deletion only if your contact allows it to you. (24 hours)</source> + <target>Consenti l'eliminazione irreversibile dei messaggi solo se il contatto la consente a te. (24 ore)</target> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="Allow message reactions only if your contact allows them." xml:space="preserve"> @@ -703,9 +708,9 @@ <target>Permetti l'invio di messaggi a tempo.</target> <note>No comment provided by engineer.</note> </trans-unit> - <trans-unit id="Allow to irreversibly delete sent messages." xml:space="preserve"> - <source>Allow to irreversibly delete sent messages.</source> - <target>Permetti di eliminare irreversibilmente i messaggi inviati.</target> + <trans-unit id="Allow to irreversibly delete sent messages. (24 hours)" xml:space="preserve"> + <source>Allow to irreversibly delete sent messages. (24 hours)</source> + <target>Permetti di eliminare irreversibilmente i messaggi inviati. (24 ore)</target> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="Allow to send files and media." xml:space="preserve"> @@ -738,9 +743,9 @@ <target>Consenti ai tuoi contatti di chiamarti.</target> <note>No comment provided by engineer.</note> </trans-unit> - <trans-unit id="Allow your contacts to irreversibly delete sent messages." xml:space="preserve"> - <source>Allow your contacts to irreversibly delete sent messages.</source> - <target>Permetti ai tuoi contatti di eliminare irreversibilmente i messaggi inviati.</target> + <trans-unit id="Allow your contacts to irreversibly delete sent messages. (24 hours)" xml:space="preserve"> + <source>Allow your contacts to irreversibly delete sent messages. (24 hours)</source> + <target>Permetti ai tuoi contatti di eliminare irreversibilmente i messaggi inviati. (24 ore)</target> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="Allow your contacts to send disappearing messages." xml:space="preserve"> @@ -918,6 +923,11 @@ <target>Blocca</target> <note>No comment provided by engineer.</note> </trans-unit> + <trans-unit id="Block for all" xml:space="preserve"> + <source>Block for all</source> + <target>Blocca per tutti</target> + <note>No comment provided by engineer.</note> + </trans-unit> <trans-unit id="Block group members" xml:space="preserve"> <source>Block group members</source> <target>Blocca i membri dei gruppi</target> @@ -928,19 +938,29 @@ <target>Blocca membro</target> <note>No comment provided by engineer.</note> </trans-unit> + <trans-unit id="Block member for all?" xml:space="preserve"> + <source>Block member for all?</source> + <target>Bloccare il membro per tutti?</target> + <note>No comment provided by engineer.</note> + </trans-unit> <trans-unit id="Block member?" xml:space="preserve"> <source>Block member?</source> <target>Bloccare il membro?</target> <note>No comment provided by engineer.</note> </trans-unit> + <trans-unit id="Blocked by admin" xml:space="preserve"> + <source>Blocked by admin</source> + <target>Bloccato dall'amministratore</target> + <note>No comment provided by engineer.</note> + </trans-unit> <trans-unit id="Both you and your contact can add message reactions." xml:space="preserve"> <source>Both you and your contact can add message reactions.</source> <target>Sia tu che il tuo contatto potete aggiungere reazioni ai messaggi.</target> <note>No comment provided by engineer.</note> </trans-unit> - <trans-unit id="Both you and your contact can irreversibly delete sent messages." xml:space="preserve"> - <source>Both you and your contact can irreversibly delete sent messages.</source> - <target>Sia tu che il tuo contatto potete eliminare irreversibilmente i messaggi inviati.</target> + <trans-unit id="Both you and your contact can irreversibly delete sent messages. (24 hours)" xml:space="preserve"> + <source>Both you and your contact can irreversibly delete sent messages. (24 hours)</source> + <target>Sia tu che il tuo contatto potete eliminare irreversibilmente i messaggi inviati. (24 ore)</target> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="Both you and your contact can make calls." xml:space="preserve"> @@ -978,9 +998,9 @@ <target>Chiamate</target> <note>No comment provided by engineer.</note> </trans-unit> - <trans-unit id="Can't delete user profile!" xml:space="preserve"> - <source>Can't delete user profile!</source> - <target>Impossibile eliminare il profilo utente!</target> + <trans-unit id="Camera not available" xml:space="preserve"> + <source>Camera not available</source> + <target>Fotocamera non disponibile</target> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="Can't invite contact!" xml:space="preserve"> @@ -1094,6 +1114,11 @@ <target>Chat fermata</target> <note>No comment provided by engineer.</note> </trans-unit> + <trans-unit id="Chat is stopped. If you already used this database on another device, you should transfer it back before starting chat." xml:space="preserve"> + <source>Chat is stopped. If you already used this database on another device, you should transfer it back before starting chat.</source> + <target>La chat è ferma. Se hai già usato questo database su un altro dispositivo, dovresti trasferirlo prima di avviare la chat.</target> + <note>No comment provided by engineer.</note> + </trans-unit> <trans-unit id="Chat preferences" xml:space="preserve"> <source>Chat preferences</source> <target>Preferenze della chat</target> @@ -1139,6 +1164,11 @@ <target>Svuotare la conversazione?</target> <note>No comment provided by engineer.</note> </trans-unit> + <trans-unit id="Clear private notes?" xml:space="preserve"> + <source>Clear private notes?</source> + <target>Svuotare le note private?</target> + <note>No comment provided by engineer.</note> + </trans-unit> <trans-unit id="Clear verification" xml:space="preserve"> <source>Clear verification</source> <target>Annulla la verifica</target> @@ -1181,7 +1211,7 @@ </trans-unit> <trans-unit id="Confirm new passphrase…" xml:space="preserve"> <source>Confirm new passphrase…</source> - <target>Conferma password nuova…</target> + <target>Conferma nuova password…</target> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="Confirm password" xml:space="preserve"> @@ -1196,6 +1226,7 @@ </trans-unit> <trans-unit id="Connect automatically" xml:space="preserve"> <source>Connect automatically</source> + <target>Connetti automaticamente</target> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="Connect incognito" xml:space="preserve"> @@ -1237,11 +1268,6 @@ Questo è il tuo link una tantum!</target> <target>Connetti via link</target> <note>No comment provided by engineer.</note> </trans-unit> - <trans-unit id="Connect via link / QR code" xml:space="preserve"> - <source>Connect via link / QR code</source> - <target>Connetti via link / codice QR</target> - <note>No comment provided by engineer.</note> - </trans-unit> <trans-unit id="Connect via one-time link" xml:space="preserve"> <source>Connect via one-time link</source> <target>Connetti via link una tantum</target> @@ -1417,11 +1443,6 @@ Questo è il tuo link una tantum!</target> <target>Crea un nuovo profilo nell'[app desktop](https://simplex.chat/downloads/). 💻</target> <note>No comment provided by engineer.</note> </trans-unit> - <trans-unit id="Create one-time invitation link" xml:space="preserve"> - <source>Create one-time invitation link</source> - <target>Crea link di invito una tantum</target> - <note>No comment provided by engineer.</note> - </trans-unit> <trans-unit id="Create profile" xml:space="preserve"> <source>Create profile</source> <target>Crea profilo</target> @@ -1442,11 +1463,26 @@ Questo è il tuo link una tantum!</target> <target>Crea il tuo profilo</target> <note>No comment provided by engineer.</note> </trans-unit> + <trans-unit id="Created at" xml:space="preserve"> + <source>Created at</source> + <target>Creato il</target> + <note>No comment provided by engineer.</note> + </trans-unit> + <trans-unit id="Created at: %@" xml:space="preserve"> + <source>Created at: %@</source> + <target>Creato il: %@</target> + <note>copied message info</note> + </trans-unit> <trans-unit id="Created on %@" xml:space="preserve"> <source>Created on %@</source> <target>Creato il %@</target> <note>No comment provided by engineer.</note> </trans-unit> + <trans-unit id="Creating link…" xml:space="preserve"> + <source>Creating link…</source> + <target>Creazione link…</target> + <note>No comment provided by engineer.</note> + </trans-unit> <trans-unit id="Current Passcode" xml:space="preserve"> <source>Current Passcode</source> <target>Codice di accesso attuale</target> @@ -1914,6 +1950,7 @@ Non è reversibile!</target> </trans-unit> <trans-unit id="Discover via local network" xml:space="preserve"> <source>Discover via local network</source> + <target>Individua via rete locale</target> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="Do NOT use SimpleX for emergency calls." xml:space="preserve"> @@ -1926,6 +1963,11 @@ Non è reversibile!</target> <target>Fallo dopo</target> <note>No comment provided by engineer.</note> </trans-unit> + <trans-unit id="Do not send history to new members." xml:space="preserve"> + <source>Do not send history to new members.</source> + <target>Non inviare la cronologia ai nuovi membri.</target> + <note>No comment provided by engineer.</note> + </trans-unit> <trans-unit id="Don't create address" xml:space="preserve"> <source>Don't create address</source> <target>Non creare un indirizzo</target> @@ -1996,6 +2038,11 @@ Non è reversibile!</target> <target>Attivare l'eliminazione automatica dei messaggi?</target> <note>No comment provided by engineer.</note> </trans-unit> + <trans-unit id="Enable camera access" xml:space="preserve"> + <source>Enable camera access</source> + <target>Attiva l'accesso alla fotocamera</target> + <note>No comment provided by engineer.</note> + </trans-unit> <trans-unit id="Enable for all" xml:space="preserve"> <source>Enable for all</source> <target>Attiva per tutti</target> @@ -2061,6 +2108,11 @@ Non è reversibile!</target> <target>Messaggio crittografato o altro evento</target> <note>notification</note> </trans-unit> + <trans-unit id="Encrypted message: app is stopped" xml:space="preserve"> + <source>Encrypted message: app is stopped</source> + <target>Messaggio cifrato: l'app è ferma</target> + <note>notification</note> + </trans-unit> <trans-unit id="Encrypted message: database error" xml:space="preserve"> <source>Encrypted message: database error</source> <target>Messaggio crittografato: errore del database</target> @@ -2206,6 +2258,11 @@ Non è reversibile!</target> <target>Errore di creazione del contatto</target> <note>No comment provided by engineer.</note> </trans-unit> + <trans-unit id="Error creating message" xml:space="preserve"> + <source>Error creating message</source> + <target>Errore di creazione del messaggio</target> + <note>No comment provided by engineer.</note> + </trans-unit> <trans-unit id="Error creating profile!" xml:space="preserve"> <source>Error creating profile!</source> <target>Errore nella creazione del profilo!</target> @@ -2291,6 +2348,11 @@ Non è reversibile!</target> <target>Errore nel caricamento dei server %@</target> <note>No comment provided by engineer.</note> </trans-unit> + <trans-unit id="Error opening chat" xml:space="preserve"> + <source>Error opening chat</source> + <target>Errore di apertura della chat</target> + <note>No comment provided by engineer.</note> + </trans-unit> <trans-unit id="Error receiving file" xml:space="preserve"> <source>Error receiving file</source> <target>Errore nella ricezione del file</target> @@ -2331,6 +2393,11 @@ Non è reversibile!</target> <target>Errore nel salvataggio della password utente</target> <note>No comment provided by engineer.</note> </trans-unit> + <trans-unit id="Error scanning code: %@" xml:space="preserve"> + <source>Error scanning code: %@</source> + <target>Errore di scansione del codice: %@</target> + <note>No comment provided by engineer.</note> + </trans-unit> <trans-unit id="Error sending email" xml:space="preserve"> <source>Error sending email</source> <target>Errore nell'invio dell'email</target> @@ -2558,6 +2625,7 @@ Non è reversibile!</target> </trans-unit> <trans-unit id="Found desktop" xml:space="preserve"> <source>Found desktop</source> + <target>Desktop trovato</target> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="French interface" xml:space="preserve"> @@ -2660,9 +2728,9 @@ Non è reversibile!</target> <target>I membri del gruppo possono aggiungere reazioni ai messaggi.</target> <note>No comment provided by engineer.</note> </trans-unit> - <trans-unit id="Group members can irreversibly delete sent messages." xml:space="preserve"> - <source>Group members can irreversibly delete sent messages.</source> - <target>I membri del gruppo possono eliminare irreversibilmente i messaggi inviati.</target> + <trans-unit id="Group members can irreversibly delete sent messages. (24 hours)" xml:space="preserve"> + <source>Group members can irreversibly delete sent messages. (24 hours)</source> + <target>I membri del gruppo possono eliminare irreversibilmente i messaggi inviati. (24 ore)</target> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="Group members can send direct messages." xml:space="preserve"> @@ -2770,6 +2838,11 @@ Non è reversibile!</target> <target>Cronologia</target> <note>No comment provided by engineer.</note> </trans-unit> + <trans-unit id="History is not sent to new members." xml:space="preserve"> + <source>History is not sent to new members.</source> + <target>La cronologia non viene inviata ai nuovi membri.</target> + <note>No comment provided by engineer.</note> + </trans-unit> <trans-unit id="How SimpleX works" xml:space="preserve"> <source>How SimpleX works</source> <target>Come funziona SimpleX</target> @@ -2805,11 +2878,6 @@ Non è reversibile!</target> <target>Se non potete incontrarvi di persona, mostra il codice QR in una videochiamata o condividi il link.</target> <note>No comment provided by engineer.</note> </trans-unit> - <trans-unit id="If you cannot meet in person, you can **scan QR code in the video call**, or your contact can share an invitation link." xml:space="preserve"> - <source>If you cannot meet in person, you can **scan QR code in the video call**, or your contact can share an invitation link.</source> - <target>Se non potete incontrarvi di persona, puoi **scansionare il codice QR durante la videochiamata** oppure il tuo contatto può condividere un link di invito.</target> - <note>No comment provided by engineer.</note> - </trans-unit> <trans-unit id="If you enter this passcode when opening the app, all app data will be irreversibly removed!" xml:space="preserve"> <source>If you enter this passcode when opening the app, all app data will be irreversibly removed!</source> <target>Se inserisci questo codice all'apertura dell'app, tutti i dati di essa verranno rimossi in modo irreversibile!</target> @@ -2865,6 +2933,11 @@ Non è reversibile!</target> <target>Importa database</target> <note>No comment provided by engineer.</note> </trans-unit> + <trans-unit id="Improved message delivery" xml:space="preserve"> + <source>Improved message delivery</source> + <target>Consegna dei messaggi migliorata</target> + <note>No comment provided by engineer.</note> + </trans-unit> <trans-unit id="Improved privacy and security" xml:space="preserve"> <source>Improved privacy and security</source> <target>Privacy e sicurezza migliorate</target> @@ -2967,16 +3040,36 @@ Non è reversibile!</target> <target>Interfaccia</target> <note>No comment provided by engineer.</note> </trans-unit> + <trans-unit id="Invalid QR code" xml:space="preserve"> + <source>Invalid QR code</source> + <target>Codice QR non valido</target> + <note>No comment provided by engineer.</note> + </trans-unit> <trans-unit id="Invalid connection link" xml:space="preserve"> <source>Invalid connection link</source> <target>Link di connessione non valido</target> <note>No comment provided by engineer.</note> </trans-unit> + <trans-unit id="Invalid display name!" xml:space="preserve"> + <source>Invalid display name!</source> + <target>Nome da mostrare non valido!</target> + <note>No comment provided by engineer.</note> + </trans-unit> + <trans-unit id="Invalid link" xml:space="preserve"> + <source>Invalid link</source> + <target>Link non valido</target> + <note>No comment provided by engineer.</note> + </trans-unit> <trans-unit id="Invalid name!" xml:space="preserve"> <source>Invalid name!</source> <target>Nome non valido!</target> <note>No comment provided by engineer.</note> </trans-unit> + <trans-unit id="Invalid response" xml:space="preserve"> + <source>Invalid response</source> + <target>Risposta non valida</target> + <note>No comment provided by engineer.</note> + </trans-unit> <trans-unit id="Invalid server address!" xml:space="preserve"> <source>Invalid server address!</source> <target>Indirizzo del server non valido!</target> @@ -3068,6 +3161,11 @@ Non è reversibile!</target> <target>Entra nel gruppo</target> <note>No comment provided by engineer.</note> </trans-unit> + <trans-unit id="Join group conversations" xml:space="preserve"> + <source>Join group conversations</source> + <target>Entra in conversazioni di gruppo</target> + <note>No comment provided by engineer.</note> + </trans-unit> <trans-unit id="Join group?" xml:space="preserve"> <source>Join group?</source> <target>Entrare nel gruppo?</target> @@ -3095,11 +3193,21 @@ Questo è il tuo link per il gruppo %@!</target> <target>Ingresso nel gruppo</target> <note>No comment provided by engineer.</note> </trans-unit> + <trans-unit id="Keep" xml:space="preserve"> + <source>Keep</source> + <target>Tieni</target> + <note>No comment provided by engineer.</note> + </trans-unit> <trans-unit id="Keep the app open to use it from desktop" xml:space="preserve"> <source>Keep the app open to use it from desktop</source> <target>Tieni aperta l'app per usarla dal desktop</target> <note>No comment provided by engineer.</note> </trans-unit> + <trans-unit id="Keep unused invitation?" xml:space="preserve"> + <source>Keep unused invitation?</source> + <target>Tenere l'invito inutilizzato?</target> + <note>No comment provided by engineer.</note> + </trans-unit> <trans-unit id="Keep your connections" xml:space="preserve"> <source>Keep your connections</source> <target>Mantieni le tue connessioni</target> @@ -3185,6 +3293,11 @@ Questo è il tuo link per il gruppo %@!</target> <target>Messaggi in diretta</target> <note>No comment provided by engineer.</note> </trans-unit> + <trans-unit id="Local" xml:space="preserve"> + <source>Local</source> + <target>Locale</target> + <note>No comment provided by engineer.</note> + </trans-unit> <trans-unit id="Local name" xml:space="preserve"> <source>Local name</source> <target>Nome locale</target> @@ -3425,6 +3538,11 @@ Questo è il tuo link per il gruppo %@!</target> <target>Nuovo codice di accesso</target> <note>No comment provided by engineer.</note> </trans-unit> + <trans-unit id="New chat" xml:space="preserve"> + <source>New chat</source> + <target>Nuova chat</target> + <note>No comment provided by engineer.</note> + </trans-unit> <trans-unit id="New contact request" xml:space="preserve"> <source>New contact request</source> <target>Nuova richiesta di contatto</target> @@ -3527,6 +3645,7 @@ Questo è il tuo link per il gruppo %@!</target> </trans-unit> <trans-unit id="Not compatible!" xml:space="preserve"> <source>Not compatible!</source> + <target>Non compatibile!</target> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="Notifications" xml:space="preserve"> @@ -3548,16 +3667,16 @@ Questo è il tuo link per il gruppo %@!</target> - disattivare i membri (ruolo "osservatore")</target> <note>No comment provided by engineer.</note> </trans-unit> + <trans-unit id="OK" xml:space="preserve"> + <source>OK</source> + <target>OK</target> + <note>No comment provided by engineer.</note> + </trans-unit> <trans-unit id="Off" xml:space="preserve"> <source>Off</source> <target>Off</target> <note>No comment provided by engineer.</note> </trans-unit> - <trans-unit id="Off (Local)" xml:space="preserve"> - <source>Off (Local)</source> - <target>Off (Locale)</target> - <note>No comment provided by engineer.</note> - </trans-unit> <trans-unit id="Ok" xml:space="preserve"> <source>Ok</source> <target>Ok</target> @@ -3618,9 +3737,9 @@ Questo è il tuo link per il gruppo %@!</target> <target>Solo tu puoi aggiungere reazioni ai messaggi.</target> <note>No comment provided by engineer.</note> </trans-unit> - <trans-unit id="Only you can irreversibly delete messages (your contact can mark them for deletion)." xml:space="preserve"> - <source>Only you can irreversibly delete messages (your contact can mark them for deletion).</source> - <target>Solo tu puoi eliminare irreversibilmente i messaggi (il tuo contatto può contrassegnarli per l'eliminazione).</target> + <trans-unit id="Only you can irreversibly delete messages (your contact can mark them for deletion). (24 hours)" xml:space="preserve"> + <source>Only you can irreversibly delete messages (your contact can mark them for deletion). (24 hours)</source> + <target>Solo tu puoi eliminare irreversibilmente i messaggi (il tuo contatto può contrassegnarli per l'eliminazione). (24 ore)</target> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="Only you can make calls." xml:space="preserve"> @@ -3643,9 +3762,9 @@ Questo è il tuo link per il gruppo %@!</target> <target>Solo il tuo contatto può aggiungere reazioni ai messaggi.</target> <note>No comment provided by engineer.</note> </trans-unit> - <trans-unit id="Only your contact can irreversibly delete messages (you can mark them for deletion)." xml:space="preserve"> - <source>Only your contact can irreversibly delete messages (you can mark them for deletion).</source> - <target>Solo il tuo contatto può eliminare irreversibilmente i messaggi (tu puoi contrassegnarli per l'eliminazione).</target> + <trans-unit id="Only your contact can irreversibly delete messages (you can mark them for deletion). (24 hours)" xml:space="preserve"> + <source>Only your contact can irreversibly delete messages (you can mark them for deletion). (24 hours)</source> + <target>Solo il tuo contatto può eliminare irreversibilmente i messaggi (tu puoi contrassegnarli per l'eliminazione). (24 ore)</target> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="Only your contact can make calls." xml:space="preserve"> @@ -3698,9 +3817,19 @@ Questo è il tuo link per il gruppo %@!</target> <target>Protocollo e codice open source: chiunque può gestire i server.</target> <note>No comment provided by engineer.</note> </trans-unit> - <trans-unit id="Opening database…" xml:space="preserve"> - <source>Opening database…</source> - <target>Apertura del database…</target> + <trans-unit id="Opening app…" xml:space="preserve"> + <source>Opening app…</source> + <target>Apertura dell'app…</target> + <note>No comment provided by engineer.</note> + </trans-unit> + <trans-unit id="Or scan QR code" xml:space="preserve"> + <source>Or scan QR code</source> + <target>O scansiona il codice QR</target> + <note>No comment provided by engineer.</note> + </trans-unit> + <trans-unit id="Or show this code" xml:space="preserve"> + <source>Or show this code</source> + <target>O mostra questo codice</target> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="PING count" xml:space="preserve"> @@ -3743,10 +3872,10 @@ Questo è il tuo link per il gruppo %@!</target> <target>Password per mostrare</target> <note>No comment provided by engineer.</note> </trans-unit> - <trans-unit id="Paste" xml:space="preserve"> - <source>Paste</source> - <target>Incolla</target> - <note>No comment provided by engineer.</note> + <trans-unit id="Past member %@" xml:space="preserve"> + <source>Past member %@</source> + <target>Membro passato %@</target> + <note>past/unknown group member</note> </trans-unit> <trans-unit id="Paste desktop address" xml:space="preserve"> <source>Paste desktop address</source> @@ -3758,15 +3887,15 @@ Questo è il tuo link per il gruppo %@!</target> <target>Incolla immagine</target> <note>No comment provided by engineer.</note> </trans-unit> - <trans-unit id="Paste received link" xml:space="preserve"> - <source>Paste received link</source> - <target>Incolla il link ricevuto</target> + <trans-unit id="Paste link to connect!" xml:space="preserve"> + <source>Paste link to connect!</source> + <target>Incolla un link per connettere!</target> <note>No comment provided by engineer.</note> </trans-unit> - <trans-unit id="Paste the link you received to connect with your contact." xml:space="preserve"> - <source>Paste the link you received to connect with your contact.</source> - <target>Incolla il link che hai ricevuto nella casella sottostante per connetterti con il tuo contatto.</target> - <note>placeholder</note> + <trans-unit id="Paste the link you received" xml:space="preserve"> + <source>Paste the link you received</source> + <target>Incolla il link che hai ricevuto</target> + <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="People can connect to you only via the links you share." xml:space="preserve"> <source>People can connect to you only via the links you share.</source> @@ -3803,6 +3932,13 @@ Questo è il tuo link per il gruppo %@!</target> <target>Controlla le preferenze tue e del tuo contatto.</target> <note>No comment provided by engineer.</note> </trans-unit> + <trans-unit id="Please contact developers. Error: %@" xml:space="preserve"> + <source>Please contact developers. +Error: %@</source> + <target>Contatta gli sviluppatori. +Errore: %@</target> + <note>No comment provided by engineer.</note> + </trans-unit> <trans-unit id="Please contact group admin." xml:space="preserve"> <source>Please contact group admin.</source> <target>Contatta l'amministratore del gruppo.</target> @@ -3888,6 +4024,11 @@ Questo è il tuo link per il gruppo %@!</target> <target>Nomi di file privati</target> <note>No comment provided by engineer.</note> </trans-unit> + <trans-unit id="Private notes" xml:space="preserve"> + <source>Private notes</source> + <target>Note private</target> + <note>name of notes to self</note> + </trans-unit> <trans-unit id="Profile and server connections" xml:space="preserve"> <source>Profile and server connections</source> <target>Profilo e connessioni al server</target> @@ -4008,6 +4149,11 @@ Questo è il tuo link per il gruppo %@!</target> <target>Maggiori informazioni nella [Guida per l'utente](https://simplex.chat/docs/guide/app-settings.html#your-simplex-contact-address).</target> <note>No comment provided by engineer.</note> </trans-unit> + <trans-unit id="Read more in [User Guide](https://simplex.chat/docs/guide/chat-profiles.html#incognito-mode)." xml:space="preserve"> + <source>Read more in [User Guide](https://simplex.chat/docs/guide/chat-profiles.html#incognito-mode).</source> + <target>Leggi di più nella [Guida utente](https://simplex.chat/docs/guide/chat-profiles.html#incognito-mode).</target> + <note>No comment provided by engineer.</note> + </trans-unit> <trans-unit id="Read more in [User Guide](https://simplex.chat/docs/guide/readme.html#connect-to-friends)." xml:space="preserve"> <source>Read more in [User Guide](https://simplex.chat/docs/guide/readme.html#connect-to-friends).</source> <target>Maggiori informazioni nella [Guida per l'utente](https://simplex.chat/docs/guide/readme.html#connect-to-friends).</target> @@ -4063,6 +4209,11 @@ Questo è il tuo link per il gruppo %@!</target> <target>Ricezione via</target> <note>No comment provided by engineer.</note> </trans-unit> + <trans-unit id="Recent history and improved [directory bot](simplex:/contact#/?v=1-4&smp=smp%3A%2F%2Fu2dS9sG8nMNURyZwqASV4yROM28Er0luVTx5X1CsMrU%3D%40smp4.simplex.im%2FeXSPwqTkKyDO3px4fLf1wx3MvPdjdLW3%23%2F%3Fv%3D1-2%26dh%3DMCowBQYDK2VuAyEAaiv6MkMH44L2TcYrt_CsX3ZvM11WgbMEUn0hkIKTOho%253D%26srv%3Do5vmywmrnaxalvz6wi3zicyftgio6psuvyniis6gco6bp6ekl4cqj4id.onion)." xml:space="preserve"> + <source>Recent history and improved [directory bot](simplex:/contact#/?v=1-4&smp=smp%3A%2F%2Fu2dS9sG8nMNURyZwqASV4yROM28Er0luVTx5X1CsMrU%3D%40smp4.simplex.im%2FeXSPwqTkKyDO3px4fLf1wx3MvPdjdLW3%23%2F%3Fv%3D1-2%26dh%3DMCowBQYDK2VuAyEAaiv6MkMH44L2TcYrt_CsX3ZvM11WgbMEUn0hkIKTOho%253D%26srv%3Do5vmywmrnaxalvz6wi3zicyftgio6psuvyniis6gco6bp6ekl4cqj4id.onion).</source> + <target>Cronologia recente e [bot della directory](simplex:/contact#/?v=1-4&smp=smp%3A%2F%2Fu2dS9sG8nMNURyZwqASV4yROM28Er0luVTx5X1CsMrU%3D%40smp4.simplex.im%2FeXSPwqTkKyDO3px4fLf1wx3MvPdjdLW3%23%2F%3Fv%3D1-2%26dh%3DMCowBQYDK2VuAyEAaiv6MkMH44L2TcYrt_CsX3ZvM11WgbMEUn0hkIKTOho%253D%26srv%3Do5vmywmrnaxalvz6wi3zicyftgio6psuvyniis6gco6bp6ekl4cqj4id.onion) migliorato.</target> + <note>No comment provided by engineer.</note> + </trans-unit> <trans-unit id="Recipients see updates as you type them." xml:space="preserve"> <source>Recipients see updates as you type them.</source> <target>I destinatari vedono gli aggiornamenti mentre li digiti.</target> @@ -4218,6 +4369,11 @@ Questo è il tuo link per il gruppo %@!</target> <target>Errore di ripristino del database</target> <note>No comment provided by engineer.</note> </trans-unit> + <trans-unit id="Retry" xml:space="preserve"> + <source>Retry</source> + <target>Riprova</target> + <note>No comment provided by engineer.</note> + </trans-unit> <trans-unit id="Reveal" xml:space="preserve"> <source>Reveal</source> <target>Rivela</target> @@ -4343,6 +4499,11 @@ Questo è il tuo link per il gruppo %@!</target> <target>I server WebRTC ICE salvati verranno rimossi</target> <note>No comment provided by engineer.</note> </trans-unit> + <trans-unit id="Saved message" xml:space="preserve"> + <source>Saved message</source> + <target>Messaggio salvato</target> + <note>message info title</note> + </trans-unit> <trans-unit id="Scan QR code" xml:space="preserve"> <source>Scan QR code</source> <target>Scansiona codice QR</target> @@ -4373,6 +4534,16 @@ Questo è il tuo link per il gruppo %@!</target> <target>Cerca</target> <note>No comment provided by engineer.</note> </trans-unit> + <trans-unit id="Search bar accepts invitation links." xml:space="preserve"> + <source>Search bar accepts invitation links.</source> + <target>La barra di ricerca accetta i link di invito.</target> + <note>No comment provided by engineer.</note> + </trans-unit> + <trans-unit id="Search or paste SimpleX link" xml:space="preserve"> + <source>Search or paste SimpleX link</source> + <target>Cerca o incolla un link SimpleX</target> + <note>No comment provided by engineer.</note> + </trans-unit> <trans-unit id="Secure queue" xml:space="preserve"> <source>Secure queue</source> <target>Coda sicura</target> @@ -4478,6 +4649,11 @@ Questo è il tuo link per il gruppo %@!</target> <target>Inviali dalla galleria o dalle tastiere personalizzate.</target> <note>No comment provided by engineer.</note> </trans-unit> + <trans-unit id="Send up to 100 last messages to new members." xml:space="preserve"> + <source>Send up to 100 last messages to new members.</source> + <target>Invia fino a 100 ultimi messaggi ai nuovi membri.</target> + <note>No comment provided by engineer.</note> + </trans-unit> <trans-unit id="Sender cancelled file transfer." xml:space="preserve"> <source>Sender cancelled file transfer.</source> <target>Il mittente ha annullato il trasferimento del file.</target> @@ -4648,9 +4824,9 @@ Questo è il tuo link per il gruppo %@!</target> <target>Condividi link</target> <note>No comment provided by engineer.</note> </trans-unit> - <trans-unit id="Share one-time invitation link" xml:space="preserve"> - <source>Share one-time invitation link</source> - <target>Condividi link di invito una tantum</target> + <trans-unit id="Share this 1-time invite link" xml:space="preserve"> + <source>Share this 1-time invite link</source> + <target>Condividi questo link di invito una tantum</target> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="Share with contacts" xml:space="preserve"> @@ -4720,7 +4896,7 @@ Questo è il tuo link per il gruppo %@!</target> </trans-unit> <trans-unit id="SimpleX contact address" xml:space="preserve"> <source>SimpleX contact address</source> - <target>Indirizzo del contatto SimpleX</target> + <target>Indirizzo di contatto SimpleX</target> <note>simplex link type</note> </trans-unit> <trans-unit id="SimpleX encrypted message or connection event" xml:space="preserve"> @@ -4773,16 +4949,16 @@ Questo è il tuo link per il gruppo %@!</target> <target>Qualcuno</target> <note>notification title</note> </trans-unit> - <trans-unit id="Start a new chat" xml:space="preserve"> - <source>Start a new chat</source> - <target>Inizia una nuova chat</target> - <note>No comment provided by engineer.</note> - </trans-unit> <trans-unit id="Start chat" xml:space="preserve"> <source>Start chat</source> <target>Avvia chat</target> <note>No comment provided by engineer.</note> </trans-unit> + <trans-unit id="Start chat?" xml:space="preserve"> + <source>Start chat?</source> + <target>Avviare la chat?</target> + <note>No comment provided by engineer.</note> + </trans-unit> <trans-unit id="Start migration" xml:space="preserve"> <source>Start migration</source> <target>Avvia la migrazione</target> @@ -4908,6 +5084,16 @@ Questo è il tuo link per il gruppo %@!</target> <target>Toccare per entrare in incognito</target> <note>No comment provided by engineer.</note> </trans-unit> + <trans-unit id="Tap to paste link" xml:space="preserve"> + <source>Tap to paste link</source> + <target>Tocca per incollare il link</target> + <note>No comment provided by engineer.</note> + </trans-unit> + <trans-unit id="Tap to scan" xml:space="preserve"> + <source>Tap to scan</source> + <target>Tocca per scansionare</target> + <note>No comment provided by engineer.</note> + </trans-unit> <trans-unit id="Tap to start a new chat" xml:space="preserve"> <source>Tap to start a new chat</source> <target>Tocca per iniziare una chat</target> @@ -4970,6 +5156,11 @@ Può accadere a causa di qualche bug o quando la connessione è compromessa.</ta <target>Il tentativo di cambiare la password del database non è stato completato.</target> <note>No comment provided by engineer.</note> </trans-unit> + <trans-unit id="The code you scanned is not a SimpleX link QR code." xml:space="preserve"> + <source>The code you scanned is not a SimpleX link QR code.</source> + <target>Il codice che hai scansionato non è un codice QR di link SimpleX.</target> + <note>No comment provided by engineer.</note> + </trans-unit> <trans-unit id="The connection you accepted will be cancelled!" xml:space="preserve"> <source>The connection you accepted will be cancelled!</source> <target>La connessione che hai accettato verrà annullata!</target> @@ -5035,21 +5226,16 @@ Può accadere a causa di qualche bug o quando la connessione è compromessa.</ta <target>I server per le nuove connessioni del profilo di chat attuale **%@**.</target> <note>No comment provided by engineer.</note> </trans-unit> + <trans-unit id="The text you pasted is not a SimpleX link." xml:space="preserve"> + <source>The text you pasted is not a SimpleX link.</source> + <target>Il testo che hai incollato non è un link SimpleX.</target> + <note>No comment provided by engineer.</note> + </trans-unit> <trans-unit id="Theme" xml:space="preserve"> <source>Theme</source> <target>Tema</target> <note>No comment provided by engineer.</note> </trans-unit> - <trans-unit id="There should be at least one user profile." xml:space="preserve"> - <source>There should be at least one user profile.</source> - <target>Deve esserci almeno un profilo utente.</target> - <note>No comment provided by engineer.</note> - </trans-unit> - <trans-unit id="There should be at least one visible user profile." xml:space="preserve"> - <source>There should be at least one visible user profile.</source> - <target>Deve esserci almeno un profilo utente visibile.</target> - <note>No comment provided by engineer.</note> - </trans-unit> <trans-unit id="These settings are for your current profile **%@**." xml:space="preserve"> <source>These settings are for your current profile **%@**.</source> <target>Queste impostazioni sono per il tuo profilo attuale **%@**.</target> @@ -5080,6 +5266,11 @@ Può accadere a causa di qualche bug o quando la connessione è compromessa.</ta <target>Il nome di questo dispositivo</target> <note>No comment provided by engineer.</note> </trans-unit> + <trans-unit id="This display name is invalid. Please choose another name." xml:space="preserve"> + <source>This display name is invalid. Please choose another name.</source> + <target>Questo nome da mostrare non è valido. Scegline un altro.</target> + <note>No comment provided by engineer.</note> + </trans-unit> <trans-unit id="This group has over %lld members, delivery receipts are not sent." xml:space="preserve"> <source>This group has over %lld members, delivery receipts are not sent.</source> <target>Questo gruppo ha più di %lld membri, le ricevute di consegna non vengono inviate.</target> @@ -5182,16 +5373,16 @@ Ti verrà chiesto di completare l'autenticazione prima di attivare questa funzio <target>Tentativo di connessione al server usato per ricevere messaggi da questo contatto.</target> <note>No comment provided by engineer.</note> </trans-unit> + <trans-unit id="Turkish interface" xml:space="preserve"> + <source>Turkish interface</source> + <target>Interfaccia in turco</target> + <note>No comment provided by engineer.</note> + </trans-unit> <trans-unit id="Turn off" xml:space="preserve"> <source>Turn off</source> <target>Spegni</target> <note>No comment provided by engineer.</note> </trans-unit> - <trans-unit id="Turn off notifications?" xml:space="preserve"> - <source>Turn off notifications?</source> - <target>Spegnere le notifiche?</target> - <note>No comment provided by engineer.</note> - </trans-unit> <trans-unit id="Turn on" xml:space="preserve"> <source>Turn on</source> <target>Attiva</target> @@ -5207,11 +5398,21 @@ Ti verrà chiesto di completare l'autenticazione prima di attivare questa funzio <target>Sblocca</target> <note>No comment provided by engineer.</note> </trans-unit> + <trans-unit id="Unblock for all" xml:space="preserve"> + <source>Unblock for all</source> + <target>Sblocca per tutti</target> + <note>No comment provided by engineer.</note> + </trans-unit> <trans-unit id="Unblock member" xml:space="preserve"> <source>Unblock member</source> <target>Sblocca membro</target> <note>No comment provided by engineer.</note> </trans-unit> + <trans-unit id="Unblock member for all?" xml:space="preserve"> + <source>Unblock member for all?</source> + <target>Sbloccare il membro per tutti?</target> + <note>No comment provided by engineer.</note> + </trans-unit> <trans-unit id="Unblock member?" xml:space="preserve"> <source>Unblock member?</source> <target>Sbloccare il membro?</target> @@ -5309,6 +5510,11 @@ Per connetterti, chiedi al tuo contatto di creare un altro link di connessione e <target>Non letto</target> <note>No comment provided by engineer.</note> </trans-unit> + <trans-unit id="Up to 100 last messages are sent to new members." xml:space="preserve"> + <source>Up to 100 last messages are sent to new members.</source> + <target>Vengono inviati ai nuovi membri fino a 100 ultimi messaggi.</target> + <note>No comment provided by engineer.</note> + </trans-unit> <trans-unit id="Update" xml:space="preserve"> <source>Update</source> <target>Aggiorna</target> @@ -5394,6 +5600,11 @@ Per connetterti, chiedi al tuo contatto di creare un altro link di connessione e <target>Usa nuovo profilo in incognito</target> <note>No comment provided by engineer.</note> </trans-unit> + <trans-unit id="Use only local notifications?" xml:space="preserve"> + <source>Use only local notifications?</source> + <target>Usare solo notifiche locali?</target> + <note>No comment provided by engineer.</note> + </trans-unit> <trans-unit id="Use server" xml:space="preserve"> <source>Use server</source> <target>Usa il server</target> @@ -5474,6 +5685,11 @@ Per connetterti, chiedi al tuo contatto di creare un altro link di connessione e <target>Vedi codice di sicurezza</target> <note>No comment provided by engineer.</note> </trans-unit> + <trans-unit id="Visible history" xml:space="preserve"> + <source>Visible history</source> + <target>Cronologia visibile</target> + <note>chat feature</note> + </trans-unit> <trans-unit id="Voice messages" xml:space="preserve"> <source>Voice messages</source> <target>Messaggi vocali</target> @@ -5501,6 +5717,7 @@ Per connetterti, chiedi al tuo contatto di creare un altro link di connessione e </trans-unit> <trans-unit id="Waiting for desktop..." xml:space="preserve"> <source>Waiting for desktop...</source> + <target>In attesa del desktop...</target> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="Waiting for file" xml:space="preserve"> @@ -5558,11 +5775,21 @@ Per connetterti, chiedi al tuo contatto di creare un altro link di connessione e <target>Quando condividi un profilo in incognito con qualcuno, questo profilo verrà utilizzato per i gruppi a cui ti invitano.</target> <note>No comment provided by engineer.</note> </trans-unit> + <trans-unit id="With encrypted files and media." xml:space="preserve"> + <source>With encrypted files and media.</source> + <target>Con file e multimediali criptati.</target> + <note>No comment provided by engineer.</note> + </trans-unit> <trans-unit id="With optional welcome message." xml:space="preserve"> <source>With optional welcome message.</source> <target>Con messaggio di benvenuto facoltativo.</target> <note>No comment provided by engineer.</note> </trans-unit> + <trans-unit id="With reduced battery usage." xml:space="preserve"> + <source>With reduced battery usage.</source> + <target>Con consumo di batteria ridotto.</target> + <note>No comment provided by engineer.</note> + </trans-unit> <trans-unit id="Wrong database passphrase" xml:space="preserve"> <source>Wrong database passphrase</source> <target>Password del database sbagliata</target> @@ -5655,11 +5882,6 @@ Ripetere la richiesta di ingresso?</target> <target>Puoi accettare chiamate dalla schermata di blocco, senza l'autenticazione del dispositivo e dell'app.</target> <note>No comment provided by engineer.</note> </trans-unit> - <trans-unit id="You can also connect by clicking the link. If it opens in the browser, click **Open in mobile app** button." xml:space="preserve"> - <source>You can also connect by clicking the link. If it opens in the browser, click **Open in mobile app** button.</source> - <target>Puoi anche connetterti cliccando il link. Se si apre nel browser, clicca il pulsante **Apri nell'app mobile**.</target> - <note>No comment provided by engineer.</note> - </trans-unit> <trans-unit id="You can create it later" xml:space="preserve"> <source>You can create it later</source> <target>Puoi crearlo più tardi</target> @@ -5680,6 +5902,11 @@ Ripetere la richiesta di ingresso?</target> <target>Puoi nascondere o silenziare un profilo utente - scorrilo verso destra.</target> <note>No comment provided by engineer.</note> </trans-unit> + <trans-unit id="You can make it visible to your SimpleX contacts via Settings." xml:space="preserve"> + <source>You can make it visible to your SimpleX contacts via Settings.</source> + <target>Puoi renderlo visibile ai tuoi contatti SimpleX nelle impostazioni.</target> + <note>No comment provided by engineer.</note> + </trans-unit> <trans-unit id="You can now send messages to %@" xml:space="preserve"> <source>You can now send messages to %@</source> <target>Ora puoi inviare messaggi a %@</target> @@ -5720,6 +5947,11 @@ Ripetere la richiesta di ingresso?</target> <target>Puoi usare il markdown per formattare i messaggi:</target> <note>No comment provided by engineer.</note> </trans-unit> + <trans-unit id="You can view invitation link again in connection details." xml:space="preserve"> + <source>You can view invitation link again in connection details.</source> + <target>Puoi vedere di nuovo il link di invito nei dettagli di connessione.</target> + <note>No comment provided by engineer.</note> + </trans-unit> <trans-unit id="You can't send messages!" xml:space="preserve"> <source>You can't send messages!</source> <target>Non puoi inviare messaggi!</target> @@ -5727,7 +5959,7 @@ Ripetere la richiesta di ingresso?</target> </trans-unit> <trans-unit id="You control through which server(s) **to receive** the messages, your contacts – the servers you use to message them." xml:space="preserve"> <source>You control through which server(s) **to receive** the messages, your contacts – the servers you use to message them.</source> - <target>Puoi controllare attraverso quale/i server **ricevere** i messaggi, i tuoi contatti – i server che usi per inviare loro i messaggi.</target> + <target>Tu decidi attraverso quale/i server **ricevere** i messaggi, i tuoi contatti quali server usi per inviare loro i messaggi.</target> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="You could not be verified; please try again." xml:space="preserve"> @@ -5909,13 +6141,6 @@ Puoi annullare questa connessione e rimuovere il contatto (e riprovare più tard <target>I tuoi contatti possono consentire l'eliminazione completa dei messaggi.</target> <note>No comment provided by engineer.</note> </trans-unit> - <trans-unit id="Your contacts in SimpleX will see it. You can change it in Settings." xml:space="preserve"> - <source>Your contacts in SimpleX will see it. -You can change it in Settings.</source> - <target>I tuoi contatti in SimpleX lo vedranno. -Puoi modificarlo nelle impostazioni.</target> - <note>No comment provided by engineer.</note> - </trans-unit> <trans-unit id="Your contacts will remain connected." xml:space="preserve"> <source>Your contacts will remain connected.</source> <target>I tuoi contatti resteranno connessi.</target> @@ -5995,7 +6220,7 @@ I server di SimpleX non possono vedere il tuo profilo.</target> </trans-unit> <trans-unit id="[Star on GitHub](https://github.com/simplex-chat/simplex-chat)" xml:space="preserve"> <source>[Star on GitHub](https://github.com/simplex-chat/simplex-chat)</source> - <target>[Stella su GitHub](https://github.com/simplex-chat/simplex-chat)</target> + <target>[Dai una stella su GitHub](https://github.com/simplex-chat/simplex-chat)</target> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="_italic_" xml:space="preserve"> @@ -6050,6 +6275,7 @@ I server di SimpleX non possono vedere il tuo profilo.</target> </trans-unit> <trans-unit id="author" xml:space="preserve"> <source>author</source> + <target>autore</target> <note>member role</note> </trans-unit> <trans-unit id="bad message ID" xml:space="preserve"> @@ -6067,6 +6293,16 @@ I server di SimpleX non possono vedere il tuo profilo.</target> <target>bloccato</target> <note>No comment provided by engineer.</note> </trans-unit> + <trans-unit id="blocked %@" xml:space="preserve"> + <source>blocked %@</source> + <target>ha bloccato %@</target> + <note>rcv group event chat item</note> + </trans-unit> + <trans-unit id="blocked by admin" xml:space="preserve"> + <source>blocked by admin</source> + <target>bloccato dall'amministratore</target> + <note>blocked chat item</note> + </trans-unit> <trans-unit id="bold" xml:space="preserve"> <source>bold</source> <target>grassetto</target> @@ -6187,6 +6423,11 @@ I server di SimpleX non possono vedere il tuo profilo.</target> <target>connessione:% @</target> <note>connection information</note> </trans-unit> + <trans-unit id="contact %@ changed to %@" xml:space="preserve"> + <source>contact %1$@ changed to %2$@</source> + <target>contatto %1$@ cambiato in %2$@</target> + <note>profile update event chat item</note> + </trans-unit> <trans-unit id="contact has e2e encryption" xml:space="preserve"> <source>contact has e2e encryption</source> <target>il contatto ha la crittografia e2e</target> @@ -6457,6 +6698,11 @@ I server di SimpleX non possono vedere il tuo profilo.</target> <target>membro</target> <note>member role</note> </trans-unit> + <trans-unit id="member %@ changed to %@" xml:space="preserve"> + <source>member %1$@ changed to %2$@</source> + <target>membro %1$@ cambiato in %2$@</target> + <note>profile update event chat item</note> + </trans-unit> <trans-unit id="member connected" xml:space="preserve"> <source>connected</source> <target>si è connesso/a</target> @@ -6579,6 +6825,16 @@ I server di SimpleX non possono vedere il tuo profilo.</target> <target>ha rimosso %@</target> <note>rcv group event chat item</note> </trans-unit> + <trans-unit id="removed contact address" xml:space="preserve"> + <source>removed contact address</source> + <target>indirizzo di contatto rimosso</target> + <note>profile update event chat item</note> + </trans-unit> + <trans-unit id="removed profile picture" xml:space="preserve"> + <source>removed profile picture</source> + <target>immagine del profilo rimossa</target> + <note>profile update event chat item</note> + </trans-unit> <trans-unit id="removed you" xml:space="preserve"> <source>removed you</source> <target>ti ha rimosso/a</target> @@ -6609,6 +6865,16 @@ I server di SimpleX non possono vedere il tuo profilo.</target> <target>invia messaggio diretto</target> <note>No comment provided by engineer.</note> </trans-unit> + <trans-unit id="set new contact address" xml:space="preserve"> + <source>set new contact address</source> + <target>impostato nuovo indirizzo di contatto</target> + <note>profile update event chat item</note> + </trans-unit> + <trans-unit id="set new profile picture" xml:space="preserve"> + <source>set new profile picture</source> + <target>impostata nuova immagine del profilo</target> + <note>profile update event chat item</note> + </trans-unit> <trans-unit id="starting…" xml:space="preserve"> <source>starting…</source> <target>avvio…</target> @@ -6624,16 +6890,31 @@ I server di SimpleX non possono vedere il tuo profilo.</target> <target>questo contatto</target> <note>notification title</note> </trans-unit> + <trans-unit id="unblocked %@" xml:space="preserve"> + <source>unblocked %@</source> + <target>ha sbloccato %@</target> + <note>rcv group event chat item</note> + </trans-unit> <trans-unit id="unknown" xml:space="preserve"> <source>unknown</source> <target>sconosciuto</target> <note>connection info</note> </trans-unit> + <trans-unit id="unknown status" xml:space="preserve"> + <source>unknown status</source> + <target>stato sconosciuto</target> + <note>No comment provided by engineer.</note> + </trans-unit> <trans-unit id="updated group profile" xml:space="preserve"> <source>updated group profile</source> - <target>profilo del gruppo aggiornato</target> + <target>ha aggiornato il profilo del gruppo</target> <note>rcv group event chat item</note> </trans-unit> + <trans-unit id="updated profile" xml:space="preserve"> + <source>updated profile</source> + <target>profilo aggiornato</target> + <note>profile update event chat item</note> + </trans-unit> <trans-unit id="v%@" xml:space="preserve"> <source>v%@</source> <target>v%@</target> @@ -6704,6 +6985,11 @@ I server di SimpleX non possono vedere il tuo profilo.</target> <target>sei un osservatore</target> <note>No comment provided by engineer.</note> </trans-unit> + <trans-unit id="you blocked %@" xml:space="preserve"> + <source>you blocked %@</source> + <target>hai bloccato %@</target> + <note>snd group event chat item</note> + </trans-unit> <trans-unit id="you changed address" xml:space="preserve"> <source>you changed address</source> <target>hai cambiato indirizzo</target> @@ -6744,6 +7030,11 @@ I server di SimpleX non possono vedere il tuo profilo.</target> <target>hai condiviso un link incognito una tantum</target> <note>chat list item description</note> </trans-unit> + <trans-unit id="you unblocked %@" xml:space="preserve"> + <source>you unblocked %@</source> + <target>hai sbloccato %@</target> + <note>snd group event chat item</note> + </trans-unit> <trans-unit id="you: " xml:space="preserve"> <source>you: </source> <target>tu: </target> diff --git a/apps/ios/SimpleX Localizations/ja.xcloc/Localized Contents/ja.xliff b/apps/ios/SimpleX Localizations/ja.xcloc/Localized Contents/ja.xliff index 11ca09ba3b..c9f93b458e 100644 --- a/apps/ios/SimpleX Localizations/ja.xcloc/Localized Contents/ja.xliff +++ b/apps/ios/SimpleX Localizations/ja.xcloc/Localized Contents/ja.xliff @@ -103,6 +103,7 @@ </trans-unit> <trans-unit id="%@ connected" xml:space="preserve"> <source>%@ connected</source> + <target>%@ 接続中</target> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="%@ is connected!" xml:space="preserve"> @@ -212,12 +213,18 @@ <source>%lld messages blocked</source> <note>No comment provided by engineer.</note> </trans-unit> + <trans-unit id="%lld messages blocked by admin" xml:space="preserve"> + <source>%lld messages blocked by admin</source> + <note>No comment provided by engineer.</note> + </trans-unit> <trans-unit id="%lld messages marked deleted" xml:space="preserve"> <source>%lld messages marked deleted</source> + <target>%lld 件のメッセージが削除されました</target> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="%lld messages moderated by %@" xml:space="preserve"> <source>%lld messages moderated by %@</source> + <target>%@ により%lld 件のメッセージが検閲されました</target> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="%lld minutes" xml:space="preserve"> @@ -303,14 +310,17 @@ <target>)</target> <note>No comment provided by engineer.</note> </trans-unit> + <trans-unit id="**Add contact**: to create a new invitation link, or connect via a link you received." xml:space="preserve"> + <source>**Add contact**: to create a new invitation link, or connect via a link you received.</source> + <note>No comment provided by engineer.</note> + </trans-unit> <trans-unit id="**Add new contact**: to create your one-time QR Code for your contact." xml:space="preserve"> <source>**Add new contact**: to create your one-time QR Code or link for your contact.</source> <target>**新しい連絡先を追加**: 連絡先のワンタイム QR コードまたはリンクを作成します。</target> <note>No comment provided by engineer.</note> </trans-unit> - <trans-unit id="**Create link / QR code** for your contact to use." xml:space="preserve"> - <source>**Create link / QR code** for your contact to use.</source> - <target>連絡先が使用する **リンク/QR コードを作成します**。</target> + <trans-unit id="**Create group**: to create a new group." xml:space="preserve"> + <source>**Create group**: to create a new group.</source> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="**More private**: check new messages every 20 minutes. Device token is shared with SimpleX Chat server, but not how many contacts or messages you have." xml:space="preserve"> @@ -323,11 +333,6 @@ <target>**最もプライベート**: SimpleX Chat 通知サーバーを使用せず、バックグラウンドで定期的にメッセージをチェックします (アプリの使用頻度によって異なります)。</target> <note>No comment provided by engineer.</note> </trans-unit> - <trans-unit id="**Paste received link** or open it in the browser and tap **Open in mobile app**." xml:space="preserve"> - <source>**Paste received link** or open it in the browser and tap **Open in mobile app**.</source> - <target>**受信したリンク**を貼り付けるか、ブラウザーで開いて [**モバイル アプリで開く**] をタップします。</target> - <note>No comment provided by engineer.</note> - </trans-unit> <trans-unit id="**Please note**: you will NOT be able to recover or change passphrase if you lose it." xml:space="preserve"> <source>**Please note**: you will NOT be able to recover or change passphrase if you lose it.</source> <target>**注意**: パスフレーズを紛失すると、パスフレーズを復元または変更できなくなります。</target> @@ -338,11 +343,6 @@ <target>**推奨**: デバイス トークンと通知は SimpleX Chat 通知サーバーに送信されますが、メッセージの内容、サイズ、送信者は送信されません。</target> <note>No comment provided by engineer.</note> </trans-unit> - <trans-unit id="**Scan QR code**: to connect to your contact in person or via video call." xml:space="preserve"> - <source>**Scan QR code**: to connect to your contact in person or via video call.</source> - <target>**QR コードをスキャン**: 直接またはビデオ通話で連絡先に接続します。</target> - <note>No comment provided by engineer.</note> - </trans-unit> <trans-unit id="**Warning**: Instant push notifications require passphrase saved in Keychain." xml:space="preserve"> <source>**Warning**: Instant push notifications require passphrase saved in Keychain.</source> <target>**警告**: 即時の プッシュ通知には、キーチェーンに保存されたパスフレーズが必要です。</target> @@ -350,17 +350,17 @@ </trans-unit> <trans-unit id="**e2e encrypted** audio call" xml:space="preserve"> <source>**e2e encrypted** audio call</source> - <target>**e2e 暗号化**された音声通話</target> + <target>**e2e 暗号化**音声通話</target> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="**e2e encrypted** video call" xml:space="preserve"> <source>**e2e encrypted** video call</source> - <target>**エンドツーエンド暗号化済み**のビデオ通話</target> + <target>**e2e暗号化**ビデオ通話</target> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="*bold*" xml:space="preserve"> <source>\*bold*</source> - <target>\*太文字*</target> + <target>\*太字*</target> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id=", " xml:space="preserve"> @@ -437,11 +437,6 @@ <target>1週間</target> <note>time interval</note> </trans-unit> - <trans-unit id="1-time link" xml:space="preserve"> - <source>1-time link</source> - <target>使い捨てのリンク</target> - <note>No comment provided by engineer.</note> - </trans-unit> <trans-unit id="5 minutes" xml:space="preserve"> <source>5 minutes</source> <target>5分</target> @@ -539,7 +534,7 @@ </trans-unit> <trans-unit id="Accept connection request?" xml:space="preserve"> <source>Accept connection request?</source> - <target>連絡を受け入れる</target> + <target>接続要求を承認?</target> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="Accept contact request from %@?" xml:space="preserve"> @@ -557,6 +552,10 @@ <target>プロフィールにアドレスを追加し、連絡先があなたのアドレスを他の人と共有できるようにします。プロフィールの更新は連絡先に送信されます。</target> <note>No comment provided by engineer.</note> </trans-unit> + <trans-unit id="Add contact" xml:space="preserve"> + <source>Add contact</source> + <note>No comment provided by engineer.</note> + </trans-unit> <trans-unit id="Add preset servers" xml:space="preserve"> <source>Add preset servers</source> <target>既存サーバを追加</target> @@ -627,6 +626,10 @@ <target>グループ全員の接続が継続します。</target> <note>No comment provided by engineer.</note> </trans-unit> + <trans-unit id="All messages will be deleted - this cannot be undone!" xml:space="preserve"> + <source>All messages will be deleted - this cannot be undone!</source> + <note>No comment provided by engineer.</note> + </trans-unit> <trans-unit id="All messages will be deleted - this cannot be undone! The messages will be deleted ONLY for you." xml:space="preserve"> <source>All messages will be deleted - this cannot be undone! The messages will be deleted ONLY for you.</source> <target>全てのメッセージが削除されます(※注意:元に戻せません!※)。削除されるのは片方あなたのメッセージのみ。</target> @@ -643,7 +646,7 @@ </trans-unit> <trans-unit id="All your contacts will remain connected. Profile update will be sent to your contacts." xml:space="preserve"> <source>All your contacts will remain connected. Profile update will be sent to your contacts.</source> - <target>あなたの連絡先が繋がったまま継続します。</target> + <target>すべての連絡先は維持されます。連絡先に更新されたプロフィールを送信します。</target> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="Allow" xml:space="preserve"> @@ -661,8 +664,8 @@ <target>連絡先が許可している場合のみ消えるメッセージを許可する。</target> <note>No comment provided by engineer.</note> </trans-unit> - <trans-unit id="Allow irreversible message deletion only if your contact allows it to you." xml:space="preserve"> - <source>Allow irreversible message deletion only if your contact allows it to you.</source> + <trans-unit id="Allow irreversible message deletion only if your contact allows it to you. (24 hours)" xml:space="preserve"> + <source>Allow irreversible message deletion only if your contact allows it to you. (24 hours)</source> <target>送信相手も永久メッセージ削除を許可する時のみに許可する。</target> <note>No comment provided by engineer.</note> </trans-unit> @@ -686,8 +689,8 @@ <target>消えるメッセージの送信を許可する。</target> <note>No comment provided by engineer.</note> </trans-unit> - <trans-unit id="Allow to irreversibly delete sent messages." xml:space="preserve"> - <source>Allow to irreversibly delete sent messages.</source> + <trans-unit id="Allow to irreversibly delete sent messages. (24 hours)" xml:space="preserve"> + <source>Allow to irreversibly delete sent messages. (24 hours)</source> <target>送信済みメッセージの永久削除を許可する。</target> <note>No comment provided by engineer.</note> </trans-unit> @@ -721,8 +724,8 @@ <target>連絡先からの通話を許可する。</target> <note>No comment provided by engineer.</note> </trans-unit> - <trans-unit id="Allow your contacts to irreversibly delete sent messages." xml:space="preserve"> - <source>Allow your contacts to irreversibly delete sent messages.</source> + <trans-unit id="Allow your contacts to irreversibly delete sent messages. (24 hours)" xml:space="preserve"> + <source>Allow your contacts to irreversibly delete sent messages. (24 hours)</source> <target>送信相手が永久メッセージ削除するのを許可する。</target> <note>No comment provided by engineer.</note> </trans-unit> @@ -896,6 +899,10 @@ <source>Block</source> <note>No comment provided by engineer.</note> </trans-unit> + <trans-unit id="Block for all" xml:space="preserve"> + <source>Block for all</source> + <note>No comment provided by engineer.</note> + </trans-unit> <trans-unit id="Block group members" xml:space="preserve"> <source>Block group members</source> <note>No comment provided by engineer.</note> @@ -904,17 +911,25 @@ <source>Block member</source> <note>No comment provided by engineer.</note> </trans-unit> + <trans-unit id="Block member for all?" xml:space="preserve"> + <source>Block member for all?</source> + <note>No comment provided by engineer.</note> + </trans-unit> <trans-unit id="Block member?" xml:space="preserve"> <source>Block member?</source> <note>No comment provided by engineer.</note> </trans-unit> + <trans-unit id="Blocked by admin" xml:space="preserve"> + <source>Blocked by admin</source> + <note>No comment provided by engineer.</note> + </trans-unit> <trans-unit id="Both you and your contact can add message reactions." xml:space="preserve"> <source>Both you and your contact can add message reactions.</source> <target>自分も相手もメッセージへのリアクションを追加できます。</target> <note>No comment provided by engineer.</note> </trans-unit> - <trans-unit id="Both you and your contact can irreversibly delete sent messages." xml:space="preserve"> - <source>Both you and your contact can irreversibly delete sent messages.</source> + <trans-unit id="Both you and your contact can irreversibly delete sent messages. (24 hours)" xml:space="preserve"> + <source>Both you and your contact can irreversibly delete sent messages. (24 hours)</source> <target>あなたと連絡相手が送信済みメッセージを永久削除できます。</target> <note>No comment provided by engineer.</note> </trans-unit> @@ -953,9 +968,8 @@ <target>通話</target> <note>No comment provided by engineer.</note> </trans-unit> - <trans-unit id="Can't delete user profile!" xml:space="preserve"> - <source>Can't delete user profile!</source> - <target>ユーザープロフィールが削除できません!</target> + <trans-unit id="Camera not available" xml:space="preserve"> + <source>Camera not available</source> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="Can't invite contact!" xml:space="preserve"> @@ -1069,6 +1083,10 @@ <target>チャットが停止してます</target> <note>No comment provided by engineer.</note> </trans-unit> + <trans-unit id="Chat is stopped. If you already used this database on another device, you should transfer it back before starting chat." xml:space="preserve"> + <source>Chat is stopped. If you already used this database on another device, you should transfer it back before starting chat.</source> + <note>No comment provided by engineer.</note> + </trans-unit> <trans-unit id="Chat preferences" xml:space="preserve"> <source>Chat preferences</source> <target>チャット設定</target> @@ -1114,6 +1132,10 @@ <target>ダイアログのクリアしますか?</target> <note>No comment provided by engineer.</note> </trans-unit> + <trans-unit id="Clear private notes?" xml:space="preserve"> + <source>Clear private notes?</source> + <note>No comment provided by engineer.</note> + </trans-unit> <trans-unit id="Clear verification" xml:space="preserve"> <source>Clear verification</source> <target>検証を消す</target> @@ -1205,14 +1227,9 @@ This is your own one-time link!</source> <target>リンク経由で接続</target> <note>No comment provided by engineer.</note> </trans-unit> - <trans-unit id="Connect via link / QR code" xml:space="preserve"> - <source>Connect via link / QR code</source> - <target>リンク・QRコード経由で接続</target> - <note>No comment provided by engineer.</note> - </trans-unit> <trans-unit id="Connect via one-time link" xml:space="preserve"> <source>Connect via one-time link</source> - <target>使い捨てリンク経由で接続しますか?</target> + <target>ワンタイムリンクで接続</target> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="Connect with %@" xml:space="preserve"> @@ -1377,11 +1394,6 @@ This is your own one-time link!</source> <target>[デスクトップアプリ](https://simplex.chat/downloads/)で新しいプロファイルを作成します。 💻</target> <note>No comment provided by engineer.</note> </trans-unit> - <trans-unit id="Create one-time invitation link" xml:space="preserve"> - <source>Create one-time invitation link</source> - <target>使い捨ての招待リンクを生成する</target> - <note>No comment provided by engineer.</note> - </trans-unit> <trans-unit id="Create profile" xml:space="preserve"> <source>Create profile</source> <note>No comment provided by engineer.</note> @@ -1401,11 +1413,23 @@ This is your own one-time link!</source> <target>プロフィールを作成する</target> <note>No comment provided by engineer.</note> </trans-unit> + <trans-unit id="Created at" xml:space="preserve"> + <source>Created at</source> + <note>No comment provided by engineer.</note> + </trans-unit> + <trans-unit id="Created at: %@" xml:space="preserve"> + <source>Created at: %@</source> + <note>copied message info</note> + </trans-unit> <trans-unit id="Created on %@" xml:space="preserve"> <source>Created on %@</source> <target>%@ によって作成されました</target> <note>No comment provided by engineer.</note> </trans-unit> + <trans-unit id="Creating link…" xml:space="preserve"> + <source>Creating link…</source> + <note>No comment provided by engineer.</note> + </trans-unit> <trans-unit id="Current Passcode" xml:space="preserve"> <source>Current Passcode</source> <target>現在のパスコード</target> @@ -1734,12 +1758,12 @@ This cannot be undone!</source> </trans-unit> <trans-unit id="Delivery" xml:space="preserve"> <source>Delivery</source> - <target>Delivery</target> + <target>配信</target> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="Delivery receipts are disabled!" xml:space="preserve"> <source>Delivery receipts are disabled!</source> - <target>Delivery receipts are disabled!</target> + <target>配信通知の停止!</target> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="Delivery receipts!" xml:space="preserve"> @@ -1877,6 +1901,10 @@ This cannot be undone!</source> <target>後で行う</target> <note>No comment provided by engineer.</note> </trans-unit> + <trans-unit id="Do not send history to new members." xml:space="preserve"> + <source>Do not send history to new members.</source> + <note>No comment provided by engineer.</note> + </trans-unit> <trans-unit id="Don't create address" xml:space="preserve"> <source>Don't create address</source> <target>アドレスを作成しないでください</target> @@ -1947,6 +1975,10 @@ This cannot be undone!</source> <target>自動メッセージ削除を有効にしますか?</target> <note>No comment provided by engineer.</note> </trans-unit> + <trans-unit id="Enable camera access" xml:space="preserve"> + <source>Enable camera access</source> + <note>No comment provided by engineer.</note> + </trans-unit> <trans-unit id="Enable for all" xml:space="preserve"> <source>Enable for all</source> <target>すべて有効</target> @@ -2012,6 +2044,10 @@ This cannot be undone!</source> <target>暗号化されたメッセージまたは別のイベント</target> <note>notification</note> </trans-unit> + <trans-unit id="Encrypted message: app is stopped" xml:space="preserve"> + <source>Encrypted message: app is stopped</source> + <note>notification</note> + </trans-unit> <trans-unit id="Encrypted message: database error" xml:space="preserve"> <source>Encrypted message: database error</source> <target>暗号化されたメッセージ : データベースエラー</target> @@ -2152,6 +2188,10 @@ This cannot be undone!</source> <target>メンバー連絡先の作成中にエラーが発生</target> <note>No comment provided by engineer.</note> </trans-unit> + <trans-unit id="Error creating message" xml:space="preserve"> + <source>Error creating message</source> + <note>No comment provided by engineer.</note> + </trans-unit> <trans-unit id="Error creating profile!" xml:space="preserve"> <source>Error creating profile!</source> <target>プロフィール作成にエラー発生!</target> @@ -2236,6 +2276,10 @@ This cannot be undone!</source> <target>%@ サーバーのロード中にエラーが発生</target> <note>No comment provided by engineer.</note> </trans-unit> + <trans-unit id="Error opening chat" xml:space="preserve"> + <source>Error opening chat</source> + <note>No comment provided by engineer.</note> + </trans-unit> <trans-unit id="Error receiving file" xml:space="preserve"> <source>Error receiving file</source> <target>ファイル受信にエラー発生</target> @@ -2276,6 +2320,10 @@ This cannot be undone!</source> <target>ユーザーパスワード保存エラー</target> <note>No comment provided by engineer.</note> </trans-unit> + <trans-unit id="Error scanning code: %@" xml:space="preserve"> + <source>Error scanning code: %@</source> + <note>No comment provided by engineer.</note> + </trans-unit> <trans-unit id="Error sending email" xml:space="preserve"> <source>Error sending email</source> <target>メールの送信にエラー発生</target> @@ -2599,8 +2647,8 @@ This cannot be undone!</source> <target>グループメンバーはメッセージへのリアクションを追加できます。</target> <note>No comment provided by engineer.</note> </trans-unit> - <trans-unit id="Group members can irreversibly delete sent messages." xml:space="preserve"> - <source>Group members can irreversibly delete sent messages.</source> + <trans-unit id="Group members can irreversibly delete sent messages. (24 hours)" xml:space="preserve"> + <source>Group members can irreversibly delete sent messages. (24 hours)</source> <target>グループのメンバーがメッセージを完全削除することができます。</target> <note>No comment provided by engineer.</note> </trans-unit> @@ -2709,6 +2757,10 @@ This cannot be undone!</source> <target>履歴</target> <note>No comment provided by engineer.</note> </trans-unit> + <trans-unit id="History is not sent to new members." xml:space="preserve"> + <source>History is not sent to new members.</source> + <note>No comment provided by engineer.</note> + </trans-unit> <trans-unit id="How SimpleX works" xml:space="preserve"> <source>How SimpleX works</source> <target>SimpleX の仕組み</target> @@ -2744,11 +2796,6 @@ This cannot be undone!</source> <target>直接会えない場合は、ビデオ通話で QR コードを表示するか、リンクを共有してください。</target> <note>No comment provided by engineer.</note> </trans-unit> - <trans-unit id="If you cannot meet in person, you can **scan QR code in the video call**, or your contact can share an invitation link." xml:space="preserve"> - <source>If you cannot meet in person, you can **scan QR code in the video call**, or your contact can share an invitation link.</source> - <target>直接会えない場合は、**ビデオ通話で QR コードを表示する**か、リンクを共有してください。</target> - <note>No comment provided by engineer.</note> - </trans-unit> <trans-unit id="If you enter this passcode when opening the app, all app data will be irreversibly removed!" xml:space="preserve"> <source>If you enter this passcode when opening the app, all app data will be irreversibly removed!</source> <target>アプリを開くときにこのパスコードを入力すると、アプリのすべてのデータが元に戻せないように削除されます!</target> @@ -2804,6 +2851,10 @@ This cannot be undone!</source> <target>データベースを読み込む</target> <note>No comment provided by engineer.</note> </trans-unit> + <trans-unit id="Improved message delivery" xml:space="preserve"> + <source>Improved message delivery</source> + <note>No comment provided by engineer.</note> + </trans-unit> <trans-unit id="Improved privacy and security" xml:space="preserve"> <source>Improved privacy and security</source> <target>プライバシーとセキュリティ強化</target> @@ -2904,15 +2955,31 @@ This cannot be undone!</source> <target>インターフェース</target> <note>No comment provided by engineer.</note> </trans-unit> + <trans-unit id="Invalid QR code" xml:space="preserve"> + <source>Invalid QR code</source> + <note>No comment provided by engineer.</note> + </trans-unit> <trans-unit id="Invalid connection link" xml:space="preserve"> <source>Invalid connection link</source> <target>無効な接続リンク</target> <note>No comment provided by engineer.</note> </trans-unit> + <trans-unit id="Invalid display name!" xml:space="preserve"> + <source>Invalid display name!</source> + <note>No comment provided by engineer.</note> + </trans-unit> + <trans-unit id="Invalid link" xml:space="preserve"> + <source>Invalid link</source> + <note>No comment provided by engineer.</note> + </trans-unit> <trans-unit id="Invalid name!" xml:space="preserve"> <source>Invalid name!</source> <note>No comment provided by engineer.</note> </trans-unit> + <trans-unit id="Invalid response" xml:space="preserve"> + <source>Invalid response</source> + <note>No comment provided by engineer.</note> + </trans-unit> <trans-unit id="Invalid server address!" xml:space="preserve"> <source>Invalid server address!</source> <target>無効なサーバアドレス!</target> @@ -3004,6 +3071,10 @@ This cannot be undone!</source> <target>グループに参加</target> <note>No comment provided by engineer.</note> </trans-unit> + <trans-unit id="Join group conversations" xml:space="preserve"> + <source>Join group conversations</source> + <note>No comment provided by engineer.</note> + </trans-unit> <trans-unit id="Join group?" xml:space="preserve"> <source>Join group?</source> <note>No comment provided by engineer.</note> @@ -3027,10 +3098,18 @@ This is your link for group %@!</source> <target>グループに参加</target> <note>No comment provided by engineer.</note> </trans-unit> + <trans-unit id="Keep" xml:space="preserve"> + <source>Keep</source> + <note>No comment provided by engineer.</note> + </trans-unit> <trans-unit id="Keep the app open to use it from desktop" xml:space="preserve"> <source>Keep the app open to use it from desktop</source> <note>No comment provided by engineer.</note> </trans-unit> + <trans-unit id="Keep unused invitation?" xml:space="preserve"> + <source>Keep unused invitation?</source> + <note>No comment provided by engineer.</note> + </trans-unit> <trans-unit id="Keep your connections" xml:space="preserve"> <source>Keep your connections</source> <target>接続を維持</target> @@ -3113,6 +3192,11 @@ This is your link for group %@!</source> <target>ライブメッセージ</target> <note>No comment provided by engineer.</note> </trans-unit> + <trans-unit id="Local" xml:space="preserve"> + <source>Local</source> + <target>自分のみ</target> + <note>No comment provided by engineer.</note> + </trans-unit> <trans-unit id="Local name" xml:space="preserve"> <source>Local name</source> <target>ローカルネーム</target> @@ -3351,6 +3435,10 @@ This is your link for group %@!</source> <target>新しいパスコード</target> <note>No comment provided by engineer.</note> </trans-unit> + <trans-unit id="New chat" xml:space="preserve"> + <source>New chat</source> + <note>No comment provided by engineer.</note> + </trans-unit> <trans-unit id="New contact request" xml:space="preserve"> <source>New contact request</source> <target>新しい繋がりのリクエスト</target> @@ -3474,16 +3562,15 @@ This is your link for group %@!</source> - メンバーを無効にする (メッセージの送信不可)</target> <note>No comment provided by engineer.</note> </trans-unit> + <trans-unit id="OK" xml:space="preserve"> + <source>OK</source> + <note>No comment provided by engineer.</note> + </trans-unit> <trans-unit id="Off" xml:space="preserve"> <source>Off</source> <target>オフ</target> <note>No comment provided by engineer.</note> </trans-unit> - <trans-unit id="Off (Local)" xml:space="preserve"> - <source>Off (Local)</source> - <target>オフ(自分のみ)</target> - <note>No comment provided by engineer.</note> - </trans-unit> <trans-unit id="Ok" xml:space="preserve"> <source>Ok</source> <target>OK</target> @@ -3544,8 +3631,8 @@ This is your link for group %@!</source> <target>メッセージへのリアクションを追加できるのは、あなただけです。</target> <note>No comment provided by engineer.</note> </trans-unit> - <trans-unit id="Only you can irreversibly delete messages (your contact can mark them for deletion)." xml:space="preserve"> - <source>Only you can irreversibly delete messages (your contact can mark them for deletion).</source> + <trans-unit id="Only you can irreversibly delete messages (your contact can mark them for deletion). (24 hours)" xml:space="preserve"> + <source>Only you can irreversibly delete messages (your contact can mark them for deletion). (24 hours)</source> <target>メッセージの完全削除はあなたにしかできません (あなたの連絡先は削除対象とすることができます)。</target> <note>No comment provided by engineer.</note> </trans-unit> @@ -3569,8 +3656,8 @@ This is your link for group %@!</source> <target>メッセージへのリアクションを追加できるのは連絡先だけです。</target> <note>No comment provided by engineer.</note> </trans-unit> - <trans-unit id="Only your contact can irreversibly delete messages (you can mark them for deletion)." xml:space="preserve"> - <source>Only your contact can irreversibly delete messages (you can mark them for deletion).</source> + <trans-unit id="Only your contact can irreversibly delete messages (you can mark them for deletion). (24 hours)" xml:space="preserve"> + <source>Only your contact can irreversibly delete messages (you can mark them for deletion). (24 hours)</source> <target>メッセージを完全削除できるのはあなたの連絡相手だけです (あなたは削除対象とすることができます)。</target> <note>No comment provided by engineer.</note> </trans-unit> @@ -3623,9 +3710,16 @@ This is your link for group %@!</source> <target>プロトコル技術とコードはオープンソースで、どなたでもご自分のサーバを運用できます。</target> <note>No comment provided by engineer.</note> </trans-unit> - <trans-unit id="Opening database…" xml:space="preserve"> - <source>Opening database…</source> - <target>データベースを開いています…</target> + <trans-unit id="Opening app…" xml:space="preserve"> + <source>Opening app…</source> + <note>No comment provided by engineer.</note> + </trans-unit> + <trans-unit id="Or scan QR code" xml:space="preserve"> + <source>Or scan QR code</source> + <note>No comment provided by engineer.</note> + </trans-unit> + <trans-unit id="Or show this code" xml:space="preserve"> + <source>Or show this code</source> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="PING count" xml:space="preserve"> @@ -3668,10 +3762,9 @@ This is your link for group %@!</source> <target>パスワードを表示する</target> <note>No comment provided by engineer.</note> </trans-unit> - <trans-unit id="Paste" xml:space="preserve"> - <source>Paste</source> - <target>貼り付け</target> - <note>No comment provided by engineer.</note> + <trans-unit id="Past member %@" xml:space="preserve"> + <source>Past member %@</source> + <note>past/unknown group member</note> </trans-unit> <trans-unit id="Paste desktop address" xml:space="preserve"> <source>Paste desktop address</source> @@ -3682,15 +3775,13 @@ This is your link for group %@!</source> <target>画像の貼り付け</target> <note>No comment provided by engineer.</note> </trans-unit> - <trans-unit id="Paste received link" xml:space="preserve"> - <source>Paste received link</source> - <target>頂いたリンクを貼り付ける</target> + <trans-unit id="Paste link to connect!" xml:space="preserve"> + <source>Paste link to connect!</source> <note>No comment provided by engineer.</note> </trans-unit> - <trans-unit id="Paste the link you received to connect with your contact." xml:space="preserve"> - <source>Paste the link you received to connect with your contact.</source> - <target>連絡相手から頂いたリンクを以下の入力欄に貼り付けて繋がります。</target> - <note>placeholder</note> + <trans-unit id="Paste the link you received" xml:space="preserve"> + <source>Paste the link you received</source> + <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="People can connect to you only via the links you share." xml:space="preserve"> <source>People can connect to you only via the links you share.</source> @@ -3727,6 +3818,11 @@ This is your link for group %@!</source> <target>あなたと連絡先の設定を確認してください。</target> <note>No comment provided by engineer.</note> </trans-unit> + <trans-unit id="Please contact developers. Error: %@" xml:space="preserve"> + <source>Please contact developers. +Error: %@</source> + <note>No comment provided by engineer.</note> + </trans-unit> <trans-unit id="Please contact group admin." xml:space="preserve"> <source>Please contact group admin.</source> <target>グループの管理者に連絡してください。</target> @@ -3812,6 +3908,10 @@ This is your link for group %@!</source> <target>プライベートなファイル名</target> <note>No comment provided by engineer.</note> </trans-unit> + <trans-unit id="Private notes" xml:space="preserve"> + <source>Private notes</source> + <note>name of notes to self</note> + </trans-unit> <trans-unit id="Profile and server connections" xml:space="preserve"> <source>Profile and server connections</source> <target>プロフィールとサーバ接続</target> @@ -3930,6 +4030,10 @@ This is your link for group %@!</source> <target>詳しくは[ユーザーガイド](https://simplex.chat/docs/guide/app-settings.html#your-simplex-contact-address)をご覧ください。</target> <note>No comment provided by engineer.</note> </trans-unit> + <trans-unit id="Read more in [User Guide](https://simplex.chat/docs/guide/chat-profiles.html#incognito-mode)." xml:space="preserve"> + <source>Read more in [User Guide](https://simplex.chat/docs/guide/chat-profiles.html#incognito-mode).</source> + <note>No comment provided by engineer.</note> + </trans-unit> <trans-unit id="Read more in [User Guide](https://simplex.chat/docs/guide/readme.html#connect-to-friends)." xml:space="preserve"> <source>Read more in [User Guide](https://simplex.chat/docs/guide/readme.html#connect-to-friends).</source> <target>詳しくは[ユーザーガイド](https://simplex.chat/docs/guide/readme.html#connect-to-friends)をご覧ください。</target> @@ -3984,6 +4088,10 @@ This is your link for group %@!</source> <target>経由で受信</target> <note>No comment provided by engineer.</note> </trans-unit> + <trans-unit id="Recent history and improved [directory bot](simplex:/contact#/?v=1-4&smp=smp%3A%2F%2Fu2dS9sG8nMNURyZwqASV4yROM28Er0luVTx5X1CsMrU%3D%40smp4.simplex.im%2FeXSPwqTkKyDO3px4fLf1wx3MvPdjdLW3%23%2F%3Fv%3D1-2%26dh%3DMCowBQYDK2VuAyEAaiv6MkMH44L2TcYrt_CsX3ZvM11WgbMEUn0hkIKTOho%253D%26srv%3Do5vmywmrnaxalvz6wi3zicyftgio6psuvyniis6gco6bp6ekl4cqj4id.onion)." xml:space="preserve"> + <source>Recent history and improved [directory bot](simplex:/contact#/?v=1-4&smp=smp%3A%2F%2Fu2dS9sG8nMNURyZwqASV4yROM28Er0luVTx5X1CsMrU%3D%40smp4.simplex.im%2FeXSPwqTkKyDO3px4fLf1wx3MvPdjdLW3%23%2F%3Fv%3D1-2%26dh%3DMCowBQYDK2VuAyEAaiv6MkMH44L2TcYrt_CsX3ZvM11WgbMEUn0hkIKTOho%253D%26srv%3Do5vmywmrnaxalvz6wi3zicyftgio6psuvyniis6gco6bp6ekl4cqj4id.onion).</source> + <note>No comment provided by engineer.</note> + </trans-unit> <trans-unit id="Recipients see updates as you type them." xml:space="preserve"> <source>Recipients see updates as you type them.</source> <target>受信者には、入力時に更新内容が表示されます。</target> @@ -4137,6 +4245,10 @@ This is your link for group %@!</source> <target>データベース復元エラー</target> <note>No comment provided by engineer.</note> </trans-unit> + <trans-unit id="Retry" xml:space="preserve"> + <source>Retry</source> + <note>No comment provided by engineer.</note> + </trans-unit> <trans-unit id="Reveal" xml:space="preserve"> <source>Reveal</source> <target>開示する</target> @@ -4262,6 +4374,10 @@ This is your link for group %@!</source> <target>保存されたWebRTC ICEサーバは削除されます</target> <note>No comment provided by engineer.</note> </trans-unit> + <trans-unit id="Saved message" xml:space="preserve"> + <source>Saved message</source> + <note>message info title</note> + </trans-unit> <trans-unit id="Scan QR code" xml:space="preserve"> <source>Scan QR code</source> <target>QRコードを読み込む</target> @@ -4291,6 +4407,14 @@ This is your link for group %@!</source> <target>検索</target> <note>No comment provided by engineer.</note> </trans-unit> + <trans-unit id="Search bar accepts invitation links." xml:space="preserve"> + <source>Search bar accepts invitation links.</source> + <note>No comment provided by engineer.</note> + </trans-unit> + <trans-unit id="Search or paste SimpleX link" xml:space="preserve"> + <source>Search or paste SimpleX link</source> + <note>No comment provided by engineer.</note> + </trans-unit> <trans-unit id="Secure queue" xml:space="preserve"> <source>Secure queue</source> <target>待ち行列セキュリティ確認</target> @@ -4394,6 +4518,10 @@ This is your link for group %@!</source> <target>ギャラリーまたはカスタム キーボードから送信します。</target> <note>No comment provided by engineer.</note> </trans-unit> + <trans-unit id="Send up to 100 last messages to new members." xml:space="preserve"> + <source>Send up to 100 last messages to new members.</source> + <note>No comment provided by engineer.</note> + </trans-unit> <trans-unit id="Sender cancelled file transfer." xml:space="preserve"> <source>Sender cancelled file transfer.</source> <target>送信者がファイル転送をキャンセルしました。</target> @@ -4557,9 +4685,8 @@ This is your link for group %@!</source> <target>リンクを送る</target> <note>No comment provided by engineer.</note> </trans-unit> - <trans-unit id="Share one-time invitation link" xml:space="preserve"> - <source>Share one-time invitation link</source> - <target>使い捨ての招待リンクを共有</target> + <trans-unit id="Share this 1-time invite link" xml:space="preserve"> + <source>Share this 1-time invite link</source> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="Share with contacts" xml:space="preserve"> @@ -4682,16 +4809,15 @@ This is your link for group %@!</source> <target>誰か</target> <note>notification title</note> </trans-unit> - <trans-unit id="Start a new chat" xml:space="preserve"> - <source>Start a new chat</source> - <target>新しいチャットを開始する</target> - <note>No comment provided by engineer.</note> - </trans-unit> <trans-unit id="Start chat" xml:space="preserve"> <source>Start chat</source> <target>チャットを開始する</target> <note>No comment provided by engineer.</note> </trans-unit> + <trans-unit id="Start chat?" xml:space="preserve"> + <source>Start chat?</source> + <note>No comment provided by engineer.</note> + </trans-unit> <trans-unit id="Start migration" xml:space="preserve"> <source>Start migration</source> <target>移行の開始</target> @@ -4816,6 +4942,14 @@ This is your link for group %@!</source> <target>タップしてシークレットモードで参加</target> <note>No comment provided by engineer.</note> </trans-unit> + <trans-unit id="Tap to paste link" xml:space="preserve"> + <source>Tap to paste link</source> + <note>No comment provided by engineer.</note> + </trans-unit> + <trans-unit id="Tap to scan" xml:space="preserve"> + <source>Tap to scan</source> + <note>No comment provided by engineer.</note> + </trans-unit> <trans-unit id="Tap to start a new chat" xml:space="preserve"> <source>Tap to start a new chat</source> <target>タップして新しいチャットを始める</target> @@ -4878,6 +5012,10 @@ It can happen because of some bug or when the connection is compromised.</source <target>データベースのパスフレーズ変更が完了してません。</target> <note>No comment provided by engineer.</note> </trans-unit> + <trans-unit id="The code you scanned is not a SimpleX link QR code." xml:space="preserve"> + <source>The code you scanned is not a SimpleX link QR code.</source> + <note>No comment provided by engineer.</note> + </trans-unit> <trans-unit id="The connection you accepted will be cancelled!" xml:space="preserve"> <source>The connection you accepted will be cancelled!</source> <target>承認済の接続がキャンセルされます!</target> @@ -4943,21 +5081,15 @@ It can happen because of some bug or when the connection is compromised.</source <target>現在のチャットプロフィールの新しい接続のサーバ **%@**。</target> <note>No comment provided by engineer.</note> </trans-unit> + <trans-unit id="The text you pasted is not a SimpleX link." xml:space="preserve"> + <source>The text you pasted is not a SimpleX link.</source> + <note>No comment provided by engineer.</note> + </trans-unit> <trans-unit id="Theme" xml:space="preserve"> <source>Theme</source> <target>テーマ</target> <note>No comment provided by engineer.</note> </trans-unit> - <trans-unit id="There should be at least one user profile." xml:space="preserve"> - <source>There should be at least one user profile.</source> - <target>少なくとも1つのユーザープロファイルが必要です。</target> - <note>No comment provided by engineer.</note> - </trans-unit> - <trans-unit id="There should be at least one visible user profile." xml:space="preserve"> - <source>There should be at least one visible user profile.</source> - <target>少なくとも1つのユーザープロフィールが表示されている必要があります。</target> - <note>No comment provided by engineer.</note> - </trans-unit> <trans-unit id="These settings are for your current profile **%@**." xml:space="preserve"> <source>These settings are for your current profile **%@**.</source> <target>これらの設定は現在のプロファイル **%@** 用です。</target> @@ -4987,6 +5119,10 @@ It can happen because of some bug or when the connection is compromised.</source <source>This device name</source> <note>No comment provided by engineer.</note> </trans-unit> + <trans-unit id="This display name is invalid. Please choose another name." xml:space="preserve"> + <source>This display name is invalid. Please choose another name.</source> + <note>No comment provided by engineer.</note> + </trans-unit> <trans-unit id="This group has over %lld members, delivery receipts are not sent." xml:space="preserve"> <source>This group has over %lld members, delivery receipts are not sent.</source> <note>No comment provided by engineer.</note> @@ -5084,16 +5220,15 @@ You will be prompted to complete authentication before this feature is enabled.< <target>このコンタクトから受信するメッセージのサーバに接続しようとしてます。</target> <note>No comment provided by engineer.</note> </trans-unit> + <trans-unit id="Turkish interface" xml:space="preserve"> + <source>Turkish interface</source> + <note>No comment provided by engineer.</note> + </trans-unit> <trans-unit id="Turn off" xml:space="preserve"> <source>Turn off</source> <target>オフにする</target> <note>No comment provided by engineer.</note> </trans-unit> - <trans-unit id="Turn off notifications?" xml:space="preserve"> - <source>Turn off notifications?</source> - <target>通知をオフにしますか?</target> - <note>No comment provided by engineer.</note> - </trans-unit> <trans-unit id="Turn on" xml:space="preserve"> <source>Turn on</source> <target>オンにする</target> @@ -5108,10 +5243,18 @@ You will be prompted to complete authentication before this feature is enabled.< <source>Unblock</source> <note>No comment provided by engineer.</note> </trans-unit> + <trans-unit id="Unblock for all" xml:space="preserve"> + <source>Unblock for all</source> + <note>No comment provided by engineer.</note> + </trans-unit> <trans-unit id="Unblock member" xml:space="preserve"> <source>Unblock member</source> <note>No comment provided by engineer.</note> </trans-unit> + <trans-unit id="Unblock member for all?" xml:space="preserve"> + <source>Unblock member for all?</source> + <note>No comment provided by engineer.</note> + </trans-unit> <trans-unit id="Unblock member?" xml:space="preserve"> <source>Unblock member?</source> <note>No comment provided by engineer.</note> @@ -5206,6 +5349,10 @@ To connect, please ask your contact to create another connection link and check <target>未読</target> <note>No comment provided by engineer.</note> </trans-unit> + <trans-unit id="Up to 100 last messages are sent to new members." xml:space="preserve"> + <source>Up to 100 last messages are sent to new members.</source> + <note>No comment provided by engineer.</note> + </trans-unit> <trans-unit id="Update" xml:space="preserve"> <source>Update</source> <target>更新</target> @@ -5290,6 +5437,10 @@ To connect, please ask your contact to create another connection link and check <target>新しいシークレットプロファイルを使用する</target> <note>No comment provided by engineer.</note> </trans-unit> + <trans-unit id="Use only local notifications?" xml:space="preserve"> + <source>Use only local notifications?</source> + <note>No comment provided by engineer.</note> + </trans-unit> <trans-unit id="Use server" xml:space="preserve"> <source>Use server</source> <target>サーバを使う</target> @@ -5366,6 +5517,10 @@ To connect, please ask your contact to create another connection link and check <target>セキュリティコードを確認</target> <note>No comment provided by engineer.</note> </trans-unit> + <trans-unit id="Visible history" xml:space="preserve"> + <source>Visible history</source> + <note>chat feature</note> + </trans-unit> <trans-unit id="Voice messages" xml:space="preserve"> <source>Voice messages</source> <target>音声メッセージ</target> @@ -5450,11 +5605,19 @@ To connect, please ask your contact to create another connection link and check <target>連絡相手にシークレットモードのプロフィールを共有すると、その連絡相手に招待されたグループでも同じプロフィールが使われます。</target> <note>No comment provided by engineer.</note> </trans-unit> + <trans-unit id="With encrypted files and media." xml:space="preserve"> + <source>With encrypted files and media.</source> + <note>No comment provided by engineer.</note> + </trans-unit> <trans-unit id="With optional welcome message." xml:space="preserve"> <source>With optional welcome message.</source> <target>任意のウェルカムメッセージ付き。</target> <note>No comment provided by engineer.</note> </trans-unit> + <trans-unit id="With reduced battery usage." xml:space="preserve"> + <source>With reduced battery usage.</source> + <note>No comment provided by engineer.</note> + </trans-unit> <trans-unit id="Wrong database passphrase" xml:space="preserve"> <source>Wrong database passphrase</source> <target>データベースのパスフレーズが違います</target> @@ -5539,11 +5702,6 @@ Repeat join request?</source> <target>デバイスやアプリの認証を行わずに、ロック画面から通話を受けることができます。</target> <note>No comment provided by engineer.</note> </trans-unit> - <trans-unit id="You can also connect by clicking the link. If it opens in the browser, click **Open in mobile app** button." xml:space="preserve"> - <source>You can also connect by clicking the link. If it opens in the browser, click **Open in mobile app** button.</source> - <target>リンクをクリックすることでも接続できます。ブラウザで開いた場合は、**モバイルアプリで開く**ボタンをクリックしてください。</target> - <note>No comment provided by engineer.</note> - </trans-unit> <trans-unit id="You can create it later" xml:space="preserve"> <source>You can create it later</source> <target>後からでも作成できます</target> @@ -5564,6 +5722,10 @@ Repeat join request?</source> <target>ユーザープロファイルを右にスワイプすると、非表示またはミュートにすることができます。</target> <note>No comment provided by engineer.</note> </trans-unit> + <trans-unit id="You can make it visible to your SimpleX contacts via Settings." xml:space="preserve"> + <source>You can make it visible to your SimpleX contacts via Settings.</source> + <note>No comment provided by engineer.</note> + </trans-unit> <trans-unit id="You can now send messages to %@" xml:space="preserve"> <source>You can now send messages to %@</source> <target>%@ にメッセージを送信できるようになりました</target> @@ -5604,6 +5766,10 @@ Repeat join request?</source> <target>メッセージの書式にmarkdownを使用することができます:</target> <note>No comment provided by engineer.</note> </trans-unit> + <trans-unit id="You can view invitation link again in connection details." xml:space="preserve"> + <source>You can view invitation link again in connection details.</source> + <note>No comment provided by engineer.</note> + </trans-unit> <trans-unit id="You can't send messages!" xml:space="preserve"> <source>You can't send messages!</source> <target>メッセージを送信できませんでした!</target> @@ -5788,13 +5954,6 @@ You can cancel this connection and remove the contact (and try later with a new <target>連絡先がメッセージの完全削除を許可できます。</target> <note>No comment provided by engineer.</note> </trans-unit> - <trans-unit id="Your contacts in SimpleX will see it. You can change it in Settings." xml:space="preserve"> - <source>Your contacts in SimpleX will see it. -You can change it in Settings.</source> - <target>SimpleX の連絡先に表示されます。 -設定で変更できます。</target> - <note>No comment provided by engineer.</note> - </trans-unit> <trans-unit id="Your contacts will remain connected." xml:space="preserve"> <source>Your contacts will remain connected.</source> <target>連絡先は接続されたままになります。</target> @@ -5943,6 +6102,14 @@ SimpleX サーバーはあなたのプロファイルを参照できません。 <source>blocked</source> <note>No comment provided by engineer.</note> </trans-unit> + <trans-unit id="blocked %@" xml:space="preserve"> + <source>blocked %@</source> + <note>rcv group event chat item</note> + </trans-unit> + <trans-unit id="blocked by admin" xml:space="preserve"> + <source>blocked by admin</source> + <note>blocked chat item</note> + </trans-unit> <trans-unit id="bold" xml:space="preserve"> <source>bold</source> <target>太文字</target> @@ -6062,6 +6229,10 @@ SimpleX サーバーはあなたのプロファイルを参照できません。 <target>接続:%@</target> <note>connection information</note> </trans-unit> + <trans-unit id="contact %@ changed to %@" xml:space="preserve"> + <source>contact %1$@ changed to %2$@</source> + <note>profile update event chat item</note> + </trans-unit> <trans-unit id="contact has e2e encryption" xml:space="preserve"> <source>contact has e2e encryption</source> <target>連絡先はエンドツーエンド暗号化があります</target> @@ -6331,6 +6502,10 @@ SimpleX サーバーはあなたのプロファイルを参照できません。 <target>メンバー</target> <note>member role</note> </trans-unit> + <trans-unit id="member %@ changed to %@" xml:space="preserve"> + <source>member %1$@ changed to %2$@</source> + <note>profile update event chat item</note> + </trans-unit> <trans-unit id="member connected" xml:space="preserve"> <source>connected</source> <target>接続中</target> @@ -6453,6 +6628,14 @@ SimpleX サーバーはあなたのプロファイルを参照できません。 <target>%@ を除名されました</target> <note>rcv group event chat item</note> </trans-unit> + <trans-unit id="removed contact address" xml:space="preserve"> + <source>removed contact address</source> + <note>profile update event chat item</note> + </trans-unit> + <trans-unit id="removed profile picture" xml:space="preserve"> + <source>removed profile picture</source> + <note>profile update event chat item</note> + </trans-unit> <trans-unit id="removed you" xml:space="preserve"> <source>removed you</source> <target>あなたを除名しました</target> @@ -6482,6 +6665,14 @@ SimpleX サーバーはあなたのプロファイルを参照できません。 <source>send direct message</source> <note>No comment provided by engineer.</note> </trans-unit> + <trans-unit id="set new contact address" xml:space="preserve"> + <source>set new contact address</source> + <note>profile update event chat item</note> + </trans-unit> + <trans-unit id="set new profile picture" xml:space="preserve"> + <source>set new profile picture</source> + <note>profile update event chat item</note> + </trans-unit> <trans-unit id="starting…" xml:space="preserve"> <source>starting…</source> <target>接続中…</target> @@ -6497,16 +6688,28 @@ SimpleX サーバーはあなたのプロファイルを参照できません。 <target>この連絡先</target> <note>notification title</note> </trans-unit> + <trans-unit id="unblocked %@" xml:space="preserve"> + <source>unblocked %@</source> + <note>rcv group event chat item</note> + </trans-unit> <trans-unit id="unknown" xml:space="preserve"> <source>unknown</source> <target>不明</target> <note>connection info</note> </trans-unit> + <trans-unit id="unknown status" xml:space="preserve"> + <source>unknown status</source> + <note>No comment provided by engineer.</note> + </trans-unit> <trans-unit id="updated group profile" xml:space="preserve"> <source>updated group profile</source> <target>グループプロフィールを更新しました</target> <note>rcv group event chat item</note> </trans-unit> + <trans-unit id="updated profile" xml:space="preserve"> + <source>updated profile</source> + <note>profile update event chat item</note> + </trans-unit> <trans-unit id="v%@" xml:space="preserve"> <source>v%@</source> <note>No comment provided by engineer.</note> @@ -6576,6 +6779,10 @@ SimpleX サーバーはあなたのプロファイルを参照できません。 <target>あなたはオブザーバーです</target> <note>No comment provided by engineer.</note> </trans-unit> + <trans-unit id="you blocked %@" xml:space="preserve"> + <source>you blocked %@</source> + <note>snd group event chat item</note> + </trans-unit> <trans-unit id="you changed address" xml:space="preserve"> <source>you changed address</source> <target>アドレスを変えました</target> @@ -6616,6 +6823,10 @@ SimpleX サーバーはあなたのプロファイルを参照できません。 <target>シークレットモードで使い捨てリンクを送りました</target> <note>chat list item description</note> </trans-unit> + <trans-unit id="you unblocked %@" xml:space="preserve"> + <source>you unblocked %@</source> + <note>snd group event chat item</note> + </trans-unit> <trans-unit id="you: " xml:space="preserve"> <source>you: </source> <target>あなた: </target> @@ -6640,12 +6851,12 @@ SimpleX サーバーはあなたのプロファイルを参照できません。 </trans-unit> <trans-unit id="NSCameraUsageDescription" xml:space="preserve"> <source>SimpleX needs camera access to scan QR codes to connect to other users and for video calls.</source> - <target>SimpleX は、他のユーザーに接続したりビデオ通話を行うために QR コードをスキャンするためにカメラにアクセスする必要があります。</target> + <target>SimpleXは他のユーザーに接続したりビデオ通話する際にQRコード読み取りのためにカメラにアクセスする必要があります。</target> <note>Privacy - Camera Usage Description</note> </trans-unit> <trans-unit id="NSFaceIDUsageDescription" xml:space="preserve"> <source>SimpleX uses Face ID for local authentication</source> - <target>SimpleX はローカル認証に Face ID を使用します</target> + <target>SimpleXはローカル認証にFace IDを使用します</target> <note>Privacy - Face ID Usage Description</note> </trans-unit> <trans-unit id="NSLocalNetworkUsageDescription" xml:space="preserve"> @@ -6654,12 +6865,12 @@ SimpleX サーバーはあなたのプロファイルを参照できません。 </trans-unit> <trans-unit id="NSMicrophoneUsageDescription" xml:space="preserve"> <source>SimpleX needs microphone access for audio and video calls, and to record voice messages.</source> - <target>SimpleX では、音声通話やビデオ通話、および音声メッセージの録音のためにマイクへのアクセスが必要です。</target> + <target>SimpleXは音声通話やビデオ通話および音声メッセージの録音のためにマイクにアクセスする必要があります。</target> <note>Privacy - Microphone Usage Description</note> </trans-unit> <trans-unit id="NSPhotoLibraryAddUsageDescription" xml:space="preserve"> <source>SimpleX needs access to Photo Library for saving captured and received media</source> - <target>SimpleX は、キャプチャおよび受信したメディアを保存するためにフォト ライブラリにアクセスする必要があります</target> + <target>SimpleXはキャプチャおよび受信したメディアを保存するためにフォトライブラリにアクセスする必要があります</target> <note>Privacy - Photo Library Additions Usage Description</note> </trans-unit> </body> diff --git a/apps/ios/SimpleX Localizations/nl.xcloc/Localized Contents/nl.xliff b/apps/ios/SimpleX Localizations/nl.xcloc/Localized Contents/nl.xliff index 094a30677a..7afd35264d 100644 --- a/apps/ios/SimpleX Localizations/nl.xcloc/Localized Contents/nl.xliff +++ b/apps/ios/SimpleX Localizations/nl.xcloc/Localized Contents/nl.xliff @@ -217,6 +217,11 @@ <target>%lld berichten geblokkeerd</target> <note>No comment provided by engineer.</note> </trans-unit> + <trans-unit id="%lld messages blocked by admin" xml:space="preserve"> + <source>%lld messages blocked by admin</source> + <target>%lld berichten geblokkeerd door beheerder</target> + <note>No comment provided by engineer.</note> + </trans-unit> <trans-unit id="%lld messages marked deleted" xml:space="preserve"> <source>%lld messages marked deleted</source> <target>%lld berichten gemarkeerd als verwijderd</target> @@ -312,14 +317,19 @@ <target>)</target> <note>No comment provided by engineer.</note> </trans-unit> + <trans-unit id="**Add contact**: to create a new invitation link, or connect via a link you received." xml:space="preserve"> + <source>**Add contact**: to create a new invitation link, or connect via a link you received.</source> + <target>**Contact toevoegen**: om een nieuwe uitnodigingslink aan te maken, of verbinding te maken via een link die u heeft ontvangen.</target> + <note>No comment provided by engineer.</note> + </trans-unit> <trans-unit id="**Add new contact**: to create your one-time QR Code for your contact." xml:space="preserve"> <source>**Add new contact**: to create your one-time QR Code or link for your contact.</source> <target>**Nieuw contact toevoegen**: om uw eenmalige QR-code of link voor uw contact te maken.</target> <note>No comment provided by engineer.</note> </trans-unit> - <trans-unit id="**Create link / QR code** for your contact to use." xml:space="preserve"> - <source>**Create link / QR code** for your contact to use.</source> - <target>**Maak een link / QR-code aan** die uw contact kan gebruiken.</target> + <trans-unit id="**Create group**: to create a new group." xml:space="preserve"> + <source>**Create group**: to create a new group.</source> + <target>**Groep aanmaken**: om een nieuwe groep aan te maken.</target> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="**More private**: check new messages every 20 minutes. Device token is shared with SimpleX Chat server, but not how many contacts or messages you have." xml:space="preserve"> @@ -332,11 +342,6 @@ <target>**Meest privé**: gebruik geen SimpleX Chat-notificatie server, controleer berichten regelmatig op de achtergrond (afhankelijk van hoe vaak u de app gebruikt).</target> <note>No comment provided by engineer.</note> </trans-unit> - <trans-unit id="**Paste received link** or open it in the browser and tap **Open in mobile app**." xml:space="preserve"> - <source>**Paste received link** or open it in the browser and tap **Open in mobile app**.</source> - <target>**Plak de ontvangen link** of open deze in de browser en tik op **Openen in mobiele app**.</target> - <note>No comment provided by engineer.</note> - </trans-unit> <trans-unit id="**Please note**: you will NOT be able to recover or change passphrase if you lose it." xml:space="preserve"> <source>**Please note**: you will NOT be able to recover or change passphrase if you lose it.</source> <target>**Let op**: u kunt het wachtwoord NIET herstellen of wijzigen als u het kwijtraakt.</target> @@ -347,11 +352,6 @@ <target>**Aanbevolen**: apparaattoken en meldingen worden naar de SimpleX Chat-meldingsserver gestuurd, maar niet de berichtinhoud, -grootte of van wie het afkomstig is.</target> <note>No comment provided by engineer.</note> </trans-unit> - <trans-unit id="**Scan QR code**: to connect to your contact in person or via video call." xml:space="preserve"> - <source>**Scan QR code**: to connect to your contact in person or via video call.</source> - <target>**Scan QR-code**: om persoonlijk of via een video gesprek verbinding te maken met uw contact.</target> - <note>No comment provided by engineer.</note> - </trans-unit> <trans-unit id="**Warning**: Instant push notifications require passphrase saved in Keychain." xml:space="preserve"> <source>**Warning**: Instant push notifications require passphrase saved in Keychain.</source> <target>**Waarschuwing**: voor directe push meldingen is een wachtwoord vereist dat is opgeslagen in de Keychain.</target> @@ -453,11 +453,6 @@ <target>1 week</target> <note>time interval</note> </trans-unit> - <trans-unit id="1-time link" xml:space="preserve"> - <source>1-time link</source> - <target>Eenmalige link</target> - <note>No comment provided by engineer.</note> - </trans-unit> <trans-unit id="5 minutes" xml:space="preserve"> <source>5 minutes</source> <target>5 minuten</target> @@ -573,6 +568,11 @@ <target>Voeg een adres toe aan uw profiel, zodat uw contacten het met andere mensen kunnen delen. Profiel update wordt naar uw contacten verzonden.</target> <note>No comment provided by engineer.</note> </trans-unit> + <trans-unit id="Add contact" xml:space="preserve"> + <source>Add contact</source> + <target>Contact toevoegen</target> + <note>No comment provided by engineer.</note> + </trans-unit> <trans-unit id="Add preset servers" xml:space="preserve"> <source>Add preset servers</source> <target>Vooraf ingestelde servers toevoegen</target> @@ -643,6 +643,11 @@ <target>Alle groepsleden blijven verbonden.</target> <note>No comment provided by engineer.</note> </trans-unit> + <trans-unit id="All messages will be deleted - this cannot be undone!" xml:space="preserve"> + <source>All messages will be deleted - this cannot be undone!</source> + <target>Alle berichten worden verwijderd. Dit kan niet ongedaan worden gemaakt!</target> + <note>No comment provided by engineer.</note> + </trans-unit> <trans-unit id="All messages will be deleted - this cannot be undone! The messages will be deleted ONLY for you." xml:space="preserve"> <source>All messages will be deleted - this cannot be undone! The messages will be deleted ONLY for you.</source> <target>Alle berichten worden verwijderd, dit kan niet ongedaan worden gemaakt! De berichten worden ALLEEN voor jou verwijderd.</target> @@ -678,9 +683,9 @@ <target>Sta verdwijnende berichten alleen toe als uw contact dit toestaat.</target> <note>No comment provided by engineer.</note> </trans-unit> - <trans-unit id="Allow irreversible message deletion only if your contact allows it to you." xml:space="preserve"> - <source>Allow irreversible message deletion only if your contact allows it to you.</source> - <target>Sta het onomkeerbaar verwijderen van berichten alleen toe als uw contact dit toestaat.</target> + <trans-unit id="Allow irreversible message deletion only if your contact allows it to you. (24 hours)" xml:space="preserve"> + <source>Allow irreversible message deletion only if your contact allows it to you. (24 hours)</source> + <target>Sta het onomkeerbaar verwijderen van berichten alleen toe als uw contact dit toestaat. (24 uur)</target> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="Allow message reactions only if your contact allows them." xml:space="preserve"> @@ -703,9 +708,9 @@ <target>Toestaan dat verdwijnende berichten worden verzonden.</target> <note>No comment provided by engineer.</note> </trans-unit> - <trans-unit id="Allow to irreversibly delete sent messages." xml:space="preserve"> - <source>Allow to irreversibly delete sent messages.</source> - <target>Sta toe om verzonden berichten onomkeerbaar te verwijderen.</target> + <trans-unit id="Allow to irreversibly delete sent messages. (24 hours)" xml:space="preserve"> + <source>Allow to irreversibly delete sent messages. (24 hours)</source> + <target>Sta toe om verzonden berichten onomkeerbaar te verwijderen. (24 uur)</target> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="Allow to send files and media." xml:space="preserve"> @@ -738,9 +743,9 @@ <target>Sta toe dat uw contacten u bellen.</target> <note>No comment provided by engineer.</note> </trans-unit> - <trans-unit id="Allow your contacts to irreversibly delete sent messages." xml:space="preserve"> - <source>Allow your contacts to irreversibly delete sent messages.</source> - <target>Laat uw contacten verzonden berichten onomkeerbaar verwijderen.</target> + <trans-unit id="Allow your contacts to irreversibly delete sent messages. (24 hours)" xml:space="preserve"> + <source>Allow your contacts to irreversibly delete sent messages. (24 hours)</source> + <target>Laat uw contacten verzonden berichten onomkeerbaar verwijderen. (24 uur)</target> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="Allow your contacts to send disappearing messages." xml:space="preserve"> @@ -770,7 +775,7 @@ </trans-unit> <trans-unit id="Always use relay" xml:space="preserve"> <source>Always use relay</source> - <target>Verbinden via relais</target> + <target>Altijd relay gebruiken</target> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="An empty chat profile with the provided name is created, and the app opens as usual." xml:space="preserve"> @@ -918,6 +923,11 @@ <target>Blokkeren</target> <note>No comment provided by engineer.</note> </trans-unit> + <trans-unit id="Block for all" xml:space="preserve"> + <source>Block for all</source> + <target>Blokkeren voor iedereen</target> + <note>No comment provided by engineer.</note> + </trans-unit> <trans-unit id="Block group members" xml:space="preserve"> <source>Block group members</source> <target>Groepsleden blokkeren</target> @@ -928,19 +938,29 @@ <target>Lid blokkeren</target> <note>No comment provided by engineer.</note> </trans-unit> + <trans-unit id="Block member for all?" xml:space="preserve"> + <source>Block member for all?</source> + <target>Lid voor iedereen blokkeren?</target> + <note>No comment provided by engineer.</note> + </trans-unit> <trans-unit id="Block member?" xml:space="preserve"> <source>Block member?</source> <target>Lid blokkeren?</target> <note>No comment provided by engineer.</note> </trans-unit> + <trans-unit id="Blocked by admin" xml:space="preserve"> + <source>Blocked by admin</source> + <target>Geblokkeerd door beheerder</target> + <note>No comment provided by engineer.</note> + </trans-unit> <trans-unit id="Both you and your contact can add message reactions." xml:space="preserve"> <source>Both you and your contact can add message reactions.</source> <target>Zowel u als uw contact kunnen berichtreacties toevoegen.</target> <note>No comment provided by engineer.</note> </trans-unit> - <trans-unit id="Both you and your contact can irreversibly delete sent messages." xml:space="preserve"> - <source>Both you and your contact can irreversibly delete sent messages.</source> - <target>Zowel jij als je contact kunnen verzonden berichten onherroepelijk verwijderen.</target> + <trans-unit id="Both you and your contact can irreversibly delete sent messages. (24 hours)" xml:space="preserve"> + <source>Both you and your contact can irreversibly delete sent messages. (24 hours)</source> + <target>Zowel jij als je contact kunnen verzonden berichten onherroepelijk verwijderen. (24 uur)</target> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="Both you and your contact can make calls." xml:space="preserve"> @@ -978,9 +998,9 @@ <target>Oproepen</target> <note>No comment provided by engineer.</note> </trans-unit> - <trans-unit id="Can't delete user profile!" xml:space="preserve"> - <source>Can't delete user profile!</source> - <target>Kan gebruikers profiel niet verwijderen!</target> + <trans-unit id="Camera not available" xml:space="preserve"> + <source>Camera not available</source> + <target>Camera niet beschikbaar</target> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="Can't invite contact!" xml:space="preserve"> @@ -1094,6 +1114,11 @@ <target>Chat is gestopt</target> <note>No comment provided by engineer.</note> </trans-unit> + <trans-unit id="Chat is stopped. If you already used this database on another device, you should transfer it back before starting chat." xml:space="preserve"> + <source>Chat is stopped. If you already used this database on another device, you should transfer it back before starting chat.</source> + <target>Chat is gestopt. Als je deze database al op een ander apparaat hebt gebruikt, moet je deze terugzetten voordat je met chatten begint.</target> + <note>No comment provided by engineer.</note> + </trans-unit> <trans-unit id="Chat preferences" xml:space="preserve"> <source>Chat preferences</source> <target>Gesprek voorkeuren</target> @@ -1139,6 +1164,11 @@ <target>Gesprek wissen?</target> <note>No comment provided by engineer.</note> </trans-unit> + <trans-unit id="Clear private notes?" xml:space="preserve"> + <source>Clear private notes?</source> + <target>Privénotities verwijderen?</target> + <note>No comment provided by engineer.</note> + </trans-unit> <trans-unit id="Clear verification" xml:space="preserve"> <source>Clear verification</source> <target>Verwijderd verificatie</target> @@ -1238,11 +1268,6 @@ Dit is uw eigen eenmalige link!</target> <target>Maak verbinding via link</target> <note>No comment provided by engineer.</note> </trans-unit> - <trans-unit id="Connect via link / QR code" xml:space="preserve"> - <source>Connect via link / QR code</source> - <target>Maak verbinding via link / QR-code</target> - <note>No comment provided by engineer.</note> - </trans-unit> <trans-unit id="Connect via one-time link" xml:space="preserve"> <source>Connect via one-time link</source> <target>Verbinden via een eenmalige link?</target> @@ -1418,11 +1443,6 @@ Dit is uw eigen eenmalige link!</target> <target>Maak een nieuw profiel aan in [desktop-app](https://simplex.chat/downloads/). 💻</target> <note>No comment provided by engineer.</note> </trans-unit> - <trans-unit id="Create one-time invitation link" xml:space="preserve"> - <source>Create one-time invitation link</source> - <target>Maak een eenmalige uitnodiging link</target> - <note>No comment provided by engineer.</note> - </trans-unit> <trans-unit id="Create profile" xml:space="preserve"> <source>Create profile</source> <target>Maak een profiel aan</target> @@ -1443,11 +1463,26 @@ Dit is uw eigen eenmalige link!</target> <target>Maak je profiel aan</target> <note>No comment provided by engineer.</note> </trans-unit> + <trans-unit id="Created at" xml:space="preserve"> + <source>Created at</source> + <target>Gemaakt op</target> + <note>No comment provided by engineer.</note> + </trans-unit> + <trans-unit id="Created at: %@" xml:space="preserve"> + <source>Created at: %@</source> + <target>Aangemaakt op: %@</target> + <note>copied message info</note> + </trans-unit> <trans-unit id="Created on %@" xml:space="preserve"> <source>Created on %@</source> <target>Gemaakt op %@</target> <note>No comment provided by engineer.</note> </trans-unit> + <trans-unit id="Creating link…" xml:space="preserve"> + <source>Creating link…</source> + <target>Link maken…</target> + <note>No comment provided by engineer.</note> + </trans-unit> <trans-unit id="Current Passcode" xml:space="preserve"> <source>Current Passcode</source> <target>Huidige toegangscode</target> @@ -1618,7 +1653,7 @@ Dit is uw eigen eenmalige link!</target> </trans-unit> <trans-unit id="Delete and notify contact" xml:space="preserve"> <source>Delete and notify contact</source> - <target>Contact verwijderen en op de hoogte stellen</target> + <target>Verwijderen en contact op de hoogte stellen</target> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="Delete archive" xml:space="preserve"> @@ -1928,6 +1963,11 @@ Dit kan niet ongedaan gemaakt worden!</target> <target>Doe het later</target> <note>No comment provided by engineer.</note> </trans-unit> + <trans-unit id="Do not send history to new members." xml:space="preserve"> + <source>Do not send history to new members.</source> + <target>Stuur geen geschiedenis naar nieuwe leden.</target> + <note>No comment provided by engineer.</note> + </trans-unit> <trans-unit id="Don't create address" xml:space="preserve"> <source>Don't create address</source> <target>Maak geen adres aan</target> @@ -1998,6 +2038,11 @@ Dit kan niet ongedaan gemaakt worden!</target> <target>Automatisch verwijderen van berichten aanzetten?</target> <note>No comment provided by engineer.</note> </trans-unit> + <trans-unit id="Enable camera access" xml:space="preserve"> + <source>Enable camera access</source> + <target>Schakel cameratoegang in</target> + <note>No comment provided by engineer.</note> + </trans-unit> <trans-unit id="Enable for all" xml:space="preserve"> <source>Enable for all</source> <target>Inschakelen voor iedereen</target> @@ -2063,6 +2108,11 @@ Dit kan niet ongedaan gemaakt worden!</target> <target>Versleuteld bericht of een andere gebeurtenis</target> <note>notification</note> </trans-unit> + <trans-unit id="Encrypted message: app is stopped" xml:space="preserve"> + <source>Encrypted message: app is stopped</source> + <target>Versleuteld bericht: app is gestopt</target> + <note>notification</note> + </trans-unit> <trans-unit id="Encrypted message: database error" xml:space="preserve"> <source>Encrypted message: database error</source> <target>Versleuteld bericht: database fout</target> @@ -2208,6 +2258,11 @@ Dit kan niet ongedaan gemaakt worden!</target> <target>Fout bij aanmaken contact</target> <note>No comment provided by engineer.</note> </trans-unit> + <trans-unit id="Error creating message" xml:space="preserve"> + <source>Error creating message</source> + <target>Fout bij het maken van een bericht</target> + <note>No comment provided by engineer.</note> + </trans-unit> <trans-unit id="Error creating profile!" xml:space="preserve"> <source>Error creating profile!</source> <target>Fout bij aanmaken van profiel!</target> @@ -2293,6 +2348,11 @@ Dit kan niet ongedaan gemaakt worden!</target> <target>Fout bij het laden van %@ servers</target> <note>No comment provided by engineer.</note> </trans-unit> + <trans-unit id="Error opening chat" xml:space="preserve"> + <source>Error opening chat</source> + <target>Fout bij het openen van de chat</target> + <note>No comment provided by engineer.</note> + </trans-unit> <trans-unit id="Error receiving file" xml:space="preserve"> <source>Error receiving file</source> <target>Fout bij ontvangen van bestand</target> @@ -2333,6 +2393,11 @@ Dit kan niet ongedaan gemaakt worden!</target> <target>Fout bij opslaan gebruikers wachtwoord</target> <note>No comment provided by engineer.</note> </trans-unit> + <trans-unit id="Error scanning code: %@" xml:space="preserve"> + <source>Error scanning code: %@</source> + <target>Fout bij het scannen van code: %@</target> + <note>No comment provided by engineer.</note> + </trans-unit> <trans-unit id="Error sending email" xml:space="preserve"> <source>Error sending email</source> <target>Fout bij het verzenden van e-mail</target> @@ -2425,7 +2490,7 @@ Dit kan niet ongedaan gemaakt worden!</target> </trans-unit> <trans-unit id="Expand" xml:space="preserve"> <source>Expand</source> - <target>Uitbreiden</target> + <target>Uitklappen</target> <note>chat item action</note> </trans-unit> <trans-unit id="Export database" xml:space="preserve"> @@ -2663,9 +2728,9 @@ Dit kan niet ongedaan gemaakt worden!</target> <target>Groepsleden kunnen berichtreacties toevoegen.</target> <note>No comment provided by engineer.</note> </trans-unit> - <trans-unit id="Group members can irreversibly delete sent messages." xml:space="preserve"> - <source>Group members can irreversibly delete sent messages.</source> - <target>Groepsleden kunnen verzonden berichten onherroepelijk verwijderen.</target> + <trans-unit id="Group members can irreversibly delete sent messages. (24 hours)" xml:space="preserve"> + <source>Group members can irreversibly delete sent messages. (24 hours)</source> + <target>Groepsleden kunnen verzonden berichten onherroepelijk verwijderen. (24 uur)</target> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="Group members can send direct messages." xml:space="preserve"> @@ -2773,6 +2838,11 @@ Dit kan niet ongedaan gemaakt worden!</target> <target>Geschiedenis</target> <note>No comment provided by engineer.</note> </trans-unit> + <trans-unit id="History is not sent to new members." xml:space="preserve"> + <source>History is not sent to new members.</source> + <target>Geschiedenis wordt niet naar nieuwe leden gestuurd.</target> + <note>No comment provided by engineer.</note> + </trans-unit> <trans-unit id="How SimpleX works" xml:space="preserve"> <source>How SimpleX works</source> <target>Hoe SimpleX werkt</target> @@ -2808,11 +2878,6 @@ Dit kan niet ongedaan gemaakt worden!</target> <target>Als je elkaar niet persoonlijk kunt ontmoeten, laat dan de QR-code zien in een videogesprek of deel de link.</target> <note>No comment provided by engineer.</note> </trans-unit> - <trans-unit id="If you cannot meet in person, you can **scan QR code in the video call**, or your contact can share an invitation link." xml:space="preserve"> - <source>If you cannot meet in person, you can **scan QR code in the video call**, or your contact can share an invitation link.</source> - <target>Als u elkaar niet persoonlijk kunt ontmoeten, kunt u **de QR-code scannen in het video gesprek**, of uw contact kan een uitnodiging link delen.</target> - <note>No comment provided by engineer.</note> - </trans-unit> <trans-unit id="If you enter this passcode when opening the app, all app data will be irreversibly removed!" xml:space="preserve"> <source>If you enter this passcode when opening the app, all app data will be irreversibly removed!</source> <target>Als u deze toegangscode invoert bij het openen van de app, worden alle app-gegevens onomkeerbaar verwijderd!</target> @@ -2868,6 +2933,11 @@ Dit kan niet ongedaan gemaakt worden!</target> <target>Database importeren</target> <note>No comment provided by engineer.</note> </trans-unit> + <trans-unit id="Improved message delivery" xml:space="preserve"> + <source>Improved message delivery</source> + <target>Verbeterde berichtbezorging</target> + <note>No comment provided by engineer.</note> + </trans-unit> <trans-unit id="Improved privacy and security" xml:space="preserve"> <source>Improved privacy and security</source> <target>Verbeterde privacy en veiligheid</target> @@ -2962,7 +3032,7 @@ Dit kan niet ongedaan gemaakt worden!</target> </trans-unit> <trans-unit id="Instantly" xml:space="preserve"> <source>Instantly</source> - <target>Meteen</target> + <target>Direct</target> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="Interface" xml:space="preserve"> @@ -2970,16 +3040,36 @@ Dit kan niet ongedaan gemaakt worden!</target> <target>Interface</target> <note>No comment provided by engineer.</note> </trans-unit> + <trans-unit id="Invalid QR code" xml:space="preserve"> + <source>Invalid QR code</source> + <target>Ongeldige QR-code</target> + <note>No comment provided by engineer.</note> + </trans-unit> <trans-unit id="Invalid connection link" xml:space="preserve"> <source>Invalid connection link</source> <target>Ongeldige verbinding link</target> <note>No comment provided by engineer.</note> </trans-unit> + <trans-unit id="Invalid display name!" xml:space="preserve"> + <source>Invalid display name!</source> + <target>Ongeldige weergavenaam!</target> + <note>No comment provided by engineer.</note> + </trans-unit> + <trans-unit id="Invalid link" xml:space="preserve"> + <source>Invalid link</source> + <target>Ongeldige link</target> + <note>No comment provided by engineer.</note> + </trans-unit> <trans-unit id="Invalid name!" xml:space="preserve"> <source>Invalid name!</source> <target>Ongeldige naam!</target> <note>No comment provided by engineer.</note> </trans-unit> + <trans-unit id="Invalid response" xml:space="preserve"> + <source>Invalid response</source> + <target>Ongeldig antwoord</target> + <note>No comment provided by engineer.</note> + </trans-unit> <trans-unit id="Invalid server address!" xml:space="preserve"> <source>Invalid server address!</source> <target>Ongeldig server adres!</target> @@ -3071,6 +3161,11 @@ Dit kan niet ongedaan gemaakt worden!</target> <target>Word lid van groep</target> <note>No comment provided by engineer.</note> </trans-unit> + <trans-unit id="Join group conversations" xml:space="preserve"> + <source>Join group conversations</source> + <target>Neem deel aan groepsgesprekken</target> + <note>No comment provided by engineer.</note> + </trans-unit> <trans-unit id="Join group?" xml:space="preserve"> <source>Join group?</source> <target>Deelnemen aan groep?</target> @@ -3098,11 +3193,21 @@ Dit is jouw link voor groep %@!</target> <target>Deel nemen aan groep</target> <note>No comment provided by engineer.</note> </trans-unit> + <trans-unit id="Keep" xml:space="preserve"> + <source>Keep</source> + <target>Bewaar</target> + <note>No comment provided by engineer.</note> + </trans-unit> <trans-unit id="Keep the app open to use it from desktop" xml:space="preserve"> <source>Keep the app open to use it from desktop</source> <target>Houd de app geopend om deze vanaf de desktop te gebruiken</target> <note>No comment provided by engineer.</note> </trans-unit> + <trans-unit id="Keep unused invitation?" xml:space="preserve"> + <source>Keep unused invitation?</source> + <target>Ongebruikte uitnodiging bewaren?</target> + <note>No comment provided by engineer.</note> + </trans-unit> <trans-unit id="Keep your connections" xml:space="preserve"> <source>Keep your connections</source> <target>Behoud uw verbindingen</target> @@ -3188,6 +3293,11 @@ Dit is jouw link voor groep %@!</target> <target>Live berichten</target> <note>No comment provided by engineer.</note> </trans-unit> + <trans-unit id="Local" xml:space="preserve"> + <source>Local</source> + <target>Lokaal</target> + <note>No comment provided by engineer.</note> + </trans-unit> <trans-unit id="Local name" xml:space="preserve"> <source>Local name</source> <target>Lokale naam</target> @@ -3428,6 +3538,11 @@ Dit is jouw link voor groep %@!</target> <target>Nieuwe toegangscode</target> <note>No comment provided by engineer.</note> </trans-unit> + <trans-unit id="New chat" xml:space="preserve"> + <source>New chat</source> + <target>Nieuw gesprek</target> + <note>No comment provided by engineer.</note> + </trans-unit> <trans-unit id="New contact request" xml:space="preserve"> <source>New contact request</source> <target>Nieuw contactverzoek</target> @@ -3552,16 +3667,16 @@ Dit is jouw link voor groep %@!</target> - schakel leden uit ("waarnemer" rol)</target> <note>No comment provided by engineer.</note> </trans-unit> + <trans-unit id="OK" xml:space="preserve"> + <source>OK</source> + <target>OK</target> + <note>No comment provided by engineer.</note> + </trans-unit> <trans-unit id="Off" xml:space="preserve"> <source>Off</source> <target>Uit</target> <note>No comment provided by engineer.</note> </trans-unit> - <trans-unit id="Off (Local)" xml:space="preserve"> - <source>Off (Local)</source> - <target>Uit (lokaal)</target> - <note>No comment provided by engineer.</note> - </trans-unit> <trans-unit id="Ok" xml:space="preserve"> <source>Ok</source> <target>OK</target> @@ -3622,9 +3737,9 @@ Dit is jouw link voor groep %@!</target> <target>Alleen jij kunt berichtreacties toevoegen.</target> <note>No comment provided by engineer.</note> </trans-unit> - <trans-unit id="Only you can irreversibly delete messages (your contact can mark them for deletion)." xml:space="preserve"> - <source>Only you can irreversibly delete messages (your contact can mark them for deletion).</source> - <target>Alleen jij kunt berichten onomkeerbaar verwijderen (je contact kan ze markeren voor verwijdering).</target> + <trans-unit id="Only you can irreversibly delete messages (your contact can mark them for deletion). (24 hours)" xml:space="preserve"> + <source>Only you can irreversibly delete messages (your contact can mark them for deletion). (24 hours)</source> + <target>Alleen jij kunt berichten onomkeerbaar verwijderen (je contact kan ze markeren voor verwijdering). (24 uur)</target> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="Only you can make calls." xml:space="preserve"> @@ -3647,9 +3762,9 @@ Dit is jouw link voor groep %@!</target> <target>Alleen uw contact kan berichtreacties toevoegen.</target> <note>No comment provided by engineer.</note> </trans-unit> - <trans-unit id="Only your contact can irreversibly delete messages (you can mark them for deletion)." xml:space="preserve"> - <source>Only your contact can irreversibly delete messages (you can mark them for deletion).</source> - <target>Alleen uw contact kan berichten onherroepelijk verwijderen (u kunt ze markeren voor verwijdering).</target> + <trans-unit id="Only your contact can irreversibly delete messages (you can mark them for deletion). (24 hours)" xml:space="preserve"> + <source>Only your contact can irreversibly delete messages (you can mark them for deletion). (24 hours)</source> + <target>Alleen uw contact kan berichten onherroepelijk verwijderen (u kunt ze markeren voor verwijdering). (24 uur)</target> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="Only your contact can make calls." xml:space="preserve"> @@ -3702,9 +3817,19 @@ Dit is jouw link voor groep %@!</target> <target>Open-source protocol en code. Iedereen kan de servers draaien.</target> <note>No comment provided by engineer.</note> </trans-unit> - <trans-unit id="Opening database…" xml:space="preserve"> - <source>Opening database…</source> - <target>Database openen…</target> + <trans-unit id="Opening app…" xml:space="preserve"> + <source>Opening app…</source> + <target>App openen…</target> + <note>No comment provided by engineer.</note> + </trans-unit> + <trans-unit id="Or scan QR code" xml:space="preserve"> + <source>Or scan QR code</source> + <target>Of scan de QR-code</target> + <note>No comment provided by engineer.</note> + </trans-unit> + <trans-unit id="Or show this code" xml:space="preserve"> + <source>Or show this code</source> + <target>Of laat deze code zien</target> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="PING count" xml:space="preserve"> @@ -3747,10 +3872,10 @@ Dit is jouw link voor groep %@!</target> <target>Wachtwoord om weer te geven</target> <note>No comment provided by engineer.</note> </trans-unit> - <trans-unit id="Paste" xml:space="preserve"> - <source>Paste</source> - <target>Plakken</target> - <note>No comment provided by engineer.</note> + <trans-unit id="Past member %@" xml:space="preserve"> + <source>Past member %@</source> + <target>Voormalig lid %@</target> + <note>past/unknown group member</note> </trans-unit> <trans-unit id="Paste desktop address" xml:space="preserve"> <source>Paste desktop address</source> @@ -3762,15 +3887,15 @@ Dit is jouw link voor groep %@!</target> <target>Afbeelding plakken</target> <note>No comment provided by engineer.</note> </trans-unit> - <trans-unit id="Paste received link" xml:space="preserve"> - <source>Paste received link</source> - <target>Plak de ontvangen link</target> + <trans-unit id="Paste link to connect!" xml:space="preserve"> + <source>Paste link to connect!</source> + <target>Plak een link om te verbinden!</target> <note>No comment provided by engineer.</note> </trans-unit> - <trans-unit id="Paste the link you received to connect with your contact." xml:space="preserve"> - <source>Paste the link you received to connect with your contact.</source> - <target>Plak de link die je hebt ontvangen in het vak hieronder om verbinding te maken met je contact.</target> - <note>placeholder</note> + <trans-unit id="Paste the link you received" xml:space="preserve"> + <source>Paste the link you received</source> + <target>Plak de link die je hebt ontvangen</target> + <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="People can connect to you only via the links you share." xml:space="preserve"> <source>People can connect to you only via the links you share.</source> @@ -3807,6 +3932,13 @@ Dit is jouw link voor groep %@!</target> <target>Controleer de uwe en uw contact voorkeuren.</target> <note>No comment provided by engineer.</note> </trans-unit> + <trans-unit id="Please contact developers. Error: %@" xml:space="preserve"> + <source>Please contact developers. +Error: %@</source> + <target>Neem contact op met ontwikkelaars. +Fout: %@</target> + <note>No comment provided by engineer.</note> + </trans-unit> <trans-unit id="Please contact group admin." xml:space="preserve"> <source>Please contact group admin.</source> <target>Neem contact op met de groep beheerder.</target> @@ -3892,6 +4024,11 @@ Dit is jouw link voor groep %@!</target> <target>Privé bestandsnamen</target> <note>No comment provided by engineer.</note> </trans-unit> + <trans-unit id="Private notes" xml:space="preserve"> + <source>Private notes</source> + <target>Privé notities</target> + <note>name of notes to self</note> + </trans-unit> <trans-unit id="Profile and server connections" xml:space="preserve"> <source>Profile and server connections</source> <target>Profiel- en serververbindingen</target> @@ -4012,6 +4149,11 @@ Dit is jouw link voor groep %@!</target> <target>Lees meer in de [Gebruikershandleiding](https://simplex.chat/docs/guide/app-settings.html#uw-simplex-contactadres).</target> <note>No comment provided by engineer.</note> </trans-unit> + <trans-unit id="Read more in [User Guide](https://simplex.chat/docs/guide/chat-profiles.html#incognito-mode)." xml:space="preserve"> + <source>Read more in [User Guide](https://simplex.chat/docs/guide/chat-profiles.html#incognito-mode).</source> + <target>Lees meer in de [Gebruikershandleiding](https://simplex.chat/docs/guide/chat-profiles.html#incognito-mode).</target> + <note>No comment provided by engineer.</note> + </trans-unit> <trans-unit id="Read more in [User Guide](https://simplex.chat/docs/guide/readme.html#connect-to-friends)." xml:space="preserve"> <source>Read more in [User Guide](https://simplex.chat/docs/guide/readme.html#connect-to-friends).</source> <target>Lees meer in de [Gebruikershandleiding](https://simplex.chat/docs/guide/readme.html#connect-to-friends).</target> @@ -4067,6 +4209,11 @@ Dit is jouw link voor groep %@!</target> <target>Ontvang via</target> <note>No comment provided by engineer.</note> </trans-unit> + <trans-unit id="Recent history and improved [directory bot](simplex:/contact#/?v=1-4&smp=smp%3A%2F%2Fu2dS9sG8nMNURyZwqASV4yROM28Er0luVTx5X1CsMrU%3D%40smp4.simplex.im%2FeXSPwqTkKyDO3px4fLf1wx3MvPdjdLW3%23%2F%3Fv%3D1-2%26dh%3DMCowBQYDK2VuAyEAaiv6MkMH44L2TcYrt_CsX3ZvM11WgbMEUn0hkIKTOho%253D%26srv%3Do5vmywmrnaxalvz6wi3zicyftgio6psuvyniis6gco6bp6ekl4cqj4id.onion)." xml:space="preserve"> + <source>Recent history and improved [directory bot](simplex:/contact#/?v=1-4&smp=smp%3A%2F%2Fu2dS9sG8nMNURyZwqASV4yROM28Er0luVTx5X1CsMrU%3D%40smp4.simplex.im%2FeXSPwqTkKyDO3px4fLf1wx3MvPdjdLW3%23%2F%3Fv%3D1-2%26dh%3DMCowBQYDK2VuAyEAaiv6MkMH44L2TcYrt_CsX3ZvM11WgbMEUn0hkIKTOho%253D%26srv%3Do5vmywmrnaxalvz6wi3zicyftgio6psuvyniis6gco6bp6ekl4cqj4id.onion).</source> + <target>Recente geschiedenis en verbeterde [directory bot](simplex:/contact#/?v=1-4&smp=smp%3A%2F%2Fu2dS9sG8nMNURyZwqASV4yROM28Er0luVTx5X1CsMrU%3D%40smp4.simplex.im%2FeXSPwqTkKyDO3px4fLf1wx3MvPdjdLW3%23%2F%3Fv%3D1-2%26dh%3DMCowBQYDK2VuAyEAaiv6MkMH44L2TcYrt_CsX3ZvM11WgbMEUn0hkIKTOho%253D%26srv%3Do5vmywmrnaxalvz6wi3zicyftgio6psuvyniis6gco6bp6ekl4cqj4id.onion).</target> + <note>No comment provided by engineer.</note> + </trans-unit> <trans-unit id="Recipients see updates as you type them." xml:space="preserve"> <source>Recipients see updates as you type them.</source> <target>Ontvangers zien updates terwijl u ze typt.</target> @@ -4222,6 +4369,11 @@ Dit is jouw link voor groep %@!</target> <target>Database fout herstellen</target> <note>No comment provided by engineer.</note> </trans-unit> + <trans-unit id="Retry" xml:space="preserve"> + <source>Retry</source> + <target>Opnieuw proberen</target> + <note>No comment provided by engineer.</note> + </trans-unit> <trans-unit id="Reveal" xml:space="preserve"> <source>Reveal</source> <target>Onthullen</target> @@ -4347,6 +4499,11 @@ Dit is jouw link voor groep %@!</target> <target>Opgeslagen WebRTC ICE servers worden verwijderd</target> <note>No comment provided by engineer.</note> </trans-unit> + <trans-unit id="Saved message" xml:space="preserve"> + <source>Saved message</source> + <target>Opgeslagen bericht</target> + <note>message info title</note> + </trans-unit> <trans-unit id="Scan QR code" xml:space="preserve"> <source>Scan QR code</source> <target>Scan QR-code</target> @@ -4377,6 +4534,16 @@ Dit is jouw link voor groep %@!</target> <target>Zoeken</target> <note>No comment provided by engineer.</note> </trans-unit> + <trans-unit id="Search bar accepts invitation links." xml:space="preserve"> + <source>Search bar accepts invitation links.</source> + <target>Zoekbalk accepteert uitnodigingslinks.</target> + <note>No comment provided by engineer.</note> + </trans-unit> + <trans-unit id="Search or paste SimpleX link" xml:space="preserve"> + <source>Search or paste SimpleX link</source> + <target>Zoek of plak een SimpleX link</target> + <note>No comment provided by engineer.</note> + </trans-unit> <trans-unit id="Secure queue" xml:space="preserve"> <source>Secure queue</source> <target>Veilige wachtrij</target> @@ -4482,6 +4649,11 @@ Dit is jouw link voor groep %@!</target> <target>Stuur ze vanuit de galerij of aangepaste toetsenborden.</target> <note>No comment provided by engineer.</note> </trans-unit> + <trans-unit id="Send up to 100 last messages to new members." xml:space="preserve"> + <source>Send up to 100 last messages to new members.</source> + <target>Stuur tot 100 laatste berichten naar nieuwe leden.</target> + <note>No comment provided by engineer.</note> + </trans-unit> <trans-unit id="Sender cancelled file transfer." xml:space="preserve"> <source>Sender cancelled file transfer.</source> <target>Afzender heeft bestandsoverdracht geannuleerd.</target> @@ -4652,9 +4824,9 @@ Dit is jouw link voor groep %@!</target> <target>Deel link</target> <note>No comment provided by engineer.</note> </trans-unit> - <trans-unit id="Share one-time invitation link" xml:space="preserve"> - <source>Share one-time invitation link</source> - <target>Eenmalige uitnodiging link delen</target> + <trans-unit id="Share this 1-time invite link" xml:space="preserve"> + <source>Share this 1-time invite link</source> + <target>Deel deze eenmalige uitnodigingslink</target> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="Share with contacts" xml:space="preserve"> @@ -4777,16 +4949,16 @@ Dit is jouw link voor groep %@!</target> <target>Iemand</target> <note>notification title</note> </trans-unit> - <trans-unit id="Start a new chat" xml:space="preserve"> - <source>Start a new chat</source> - <target>Begin een nieuw gesprek</target> - <note>No comment provided by engineer.</note> - </trans-unit> <trans-unit id="Start chat" xml:space="preserve"> <source>Start chat</source> <target>Begin gesprek</target> <note>No comment provided by engineer.</note> </trans-unit> + <trans-unit id="Start chat?" xml:space="preserve"> + <source>Start chat?</source> + <target>Begin chat?</target> + <note>No comment provided by engineer.</note> + </trans-unit> <trans-unit id="Start migration" xml:space="preserve"> <source>Start migration</source> <target>Start migratie</target> @@ -4912,6 +5084,16 @@ Dit is jouw link voor groep %@!</target> <target>Tik om incognito lid te worden</target> <note>No comment provided by engineer.</note> </trans-unit> + <trans-unit id="Tap to paste link" xml:space="preserve"> + <source>Tap to paste link</source> + <target>Tik om de link te plakken</target> + <note>No comment provided by engineer.</note> + </trans-unit> + <trans-unit id="Tap to scan" xml:space="preserve"> + <source>Tap to scan</source> + <target>Tik om te scannen</target> + <note>No comment provided by engineer.</note> + </trans-unit> <trans-unit id="Tap to start a new chat" xml:space="preserve"> <source>Tap to start a new chat</source> <target>Tik om een nieuw gesprek te starten</target> @@ -4974,6 +5156,11 @@ Het kan gebeuren vanwege een bug of wanneer de verbinding is aangetast.</target> <target>De poging om het wachtwoord van de database te wijzigen is niet voltooid.</target> <note>No comment provided by engineer.</note> </trans-unit> + <trans-unit id="The code you scanned is not a SimpleX link QR code." xml:space="preserve"> + <source>The code you scanned is not a SimpleX link QR code.</source> + <target>De code die u heeft gescand is geen SimpleX link QR-code.</target> + <note>No comment provided by engineer.</note> + </trans-unit> <trans-unit id="The connection you accepted will be cancelled!" xml:space="preserve"> <source>The connection you accepted will be cancelled!</source> <target>De door u geaccepteerde verbinding wordt geannuleerd!</target> @@ -5039,21 +5226,16 @@ Het kan gebeuren vanwege een bug of wanneer de verbinding is aangetast.</target> <target>De servers voor nieuwe verbindingen van uw huidige chat profiel **%@**.</target> <note>No comment provided by engineer.</note> </trans-unit> + <trans-unit id="The text you pasted is not a SimpleX link." xml:space="preserve"> + <source>The text you pasted is not a SimpleX link.</source> + <target>De tekst die u hebt geplakt is geen SimpleX link.</target> + <note>No comment provided by engineer.</note> + </trans-unit> <trans-unit id="Theme" xml:space="preserve"> <source>Theme</source> <target>Thema</target> <note>No comment provided by engineer.</note> </trans-unit> - <trans-unit id="There should be at least one user profile." xml:space="preserve"> - <source>There should be at least one user profile.</source> - <target>Er moet ten minste één gebruikers profiel zijn.</target> - <note>No comment provided by engineer.</note> - </trans-unit> - <trans-unit id="There should be at least one visible user profile." xml:space="preserve"> - <source>There should be at least one visible user profile.</source> - <target>Er moet ten minste één zichtbaar gebruikers profiel zijn.</target> - <note>No comment provided by engineer.</note> - </trans-unit> <trans-unit id="These settings are for your current profile **%@**." xml:space="preserve"> <source>These settings are for your current profile **%@**.</source> <target>Deze instellingen zijn voor uw huidige profiel **%@**.</target> @@ -5084,6 +5266,11 @@ Het kan gebeuren vanwege een bug of wanneer de verbinding is aangetast.</target> <target>Deze apparaatnaam</target> <note>No comment provided by engineer.</note> </trans-unit> + <trans-unit id="This display name is invalid. Please choose another name." xml:space="preserve"> + <source>This display name is invalid. Please choose another name.</source> + <target>Deze weergavenaam is ongeldig. Kies een andere naam.</target> + <note>No comment provided by engineer.</note> + </trans-unit> <trans-unit id="This group has over %lld members, delivery receipts are not sent." xml:space="preserve"> <source>This group has over %lld members, delivery receipts are not sent.</source> <target>Deze groep heeft meer dan %lld -leden, ontvangstbevestigingen worden niet verzonden.</target> @@ -5186,16 +5373,16 @@ U wordt gevraagd de authenticatie te voltooien voordat deze functie wordt ingesc <target>Proberen verbinding te maken met de server die wordt gebruikt om berichten van dit contact te ontvangen.</target> <note>No comment provided by engineer.</note> </trans-unit> + <trans-unit id="Turkish interface" xml:space="preserve"> + <source>Turkish interface</source> + <target>Turkse interface</target> + <note>No comment provided by engineer.</note> + </trans-unit> <trans-unit id="Turn off" xml:space="preserve"> <source>Turn off</source> <target>Uitschakelen</target> <note>No comment provided by engineer.</note> </trans-unit> - <trans-unit id="Turn off notifications?" xml:space="preserve"> - <source>Turn off notifications?</source> - <target>Schakel meldingen uit?</target> - <note>No comment provided by engineer.</note> - </trans-unit> <trans-unit id="Turn on" xml:space="preserve"> <source>Turn on</source> <target>Zet aan</target> @@ -5211,11 +5398,21 @@ U wordt gevraagd de authenticatie te voltooien voordat deze functie wordt ingesc <target>Deblokkeren</target> <note>No comment provided by engineer.</note> </trans-unit> + <trans-unit id="Unblock for all" xml:space="preserve"> + <source>Unblock for all</source> + <target>Deblokkeer voor iedereen</target> + <note>No comment provided by engineer.</note> + </trans-unit> <trans-unit id="Unblock member" xml:space="preserve"> <source>Unblock member</source> <target>Lid deblokkeren</target> <note>No comment provided by engineer.</note> </trans-unit> + <trans-unit id="Unblock member for all?" xml:space="preserve"> + <source>Unblock member for all?</source> + <target>Lid voor iedereen deblokkeren?</target> + <note>No comment provided by engineer.</note> + </trans-unit> <trans-unit id="Unblock member?" xml:space="preserve"> <source>Unblock member?</source> <target>Lid deblokkeren?</target> @@ -5313,6 +5510,11 @@ Om verbinding te maken, vraagt u uw contact om een andere verbinding link te mak <target>Ongelezen</target> <note>No comment provided by engineer.</note> </trans-unit> + <trans-unit id="Up to 100 last messages are sent to new members." xml:space="preserve"> + <source>Up to 100 last messages are sent to new members.</source> + <target>Er worden maximaal 100 laatste berichten naar nieuwe leden verzonden.</target> + <note>No comment provided by engineer.</note> + </trans-unit> <trans-unit id="Update" xml:space="preserve"> <source>Update</source> <target>Update</target> @@ -5398,6 +5600,11 @@ Om verbinding te maken, vraagt u uw contact om een andere verbinding link te mak <target>Gebruik een nieuw incognitoprofiel</target> <note>No comment provided by engineer.</note> </trans-unit> + <trans-unit id="Use only local notifications?" xml:space="preserve"> + <source>Use only local notifications?</source> + <target>Alleen lokale meldingen gebruiken?</target> + <note>No comment provided by engineer.</note> + </trans-unit> <trans-unit id="Use server" xml:space="preserve"> <source>Use server</source> <target>Gebruik server</target> @@ -5478,6 +5685,11 @@ Om verbinding te maken, vraagt u uw contact om een andere verbinding link te mak <target>Beveiligingscode bekijken</target> <note>No comment provided by engineer.</note> </trans-unit> + <trans-unit id="Visible history" xml:space="preserve"> + <source>Visible history</source> + <target>Zichtbare geschiedenis</target> + <note>chat feature</note> + </trans-unit> <trans-unit id="Voice messages" xml:space="preserve"> <source>Voice messages</source> <target>Spraak berichten</target> @@ -5563,11 +5775,21 @@ Om verbinding te maken, vraagt u uw contact om een andere verbinding link te mak <target>Wanneer je een incognito profiel met iemand deelt, wordt dit profiel gebruikt voor de groepen waarvoor ze je uitnodigen.</target> <note>No comment provided by engineer.</note> </trans-unit> + <trans-unit id="With encrypted files and media." xml:space="preserve"> + <source>With encrypted files and media.</source> + <target>‐Met versleutelde bestanden en media.</target> + <note>No comment provided by engineer.</note> + </trans-unit> <trans-unit id="With optional welcome message." xml:space="preserve"> <source>With optional welcome message.</source> <target>Met optioneel welkomst bericht.</target> <note>No comment provided by engineer.</note> </trans-unit> + <trans-unit id="With reduced battery usage." xml:space="preserve"> + <source>With reduced battery usage.</source> + <target>Met verminderd batterijgebruik.</target> + <note>No comment provided by engineer.</note> + </trans-unit> <trans-unit id="Wrong database passphrase" xml:space="preserve"> <source>Wrong database passphrase</source> <target>Verkeerd wachtwoord voor de database</target> @@ -5660,11 +5882,6 @@ Deelnameverzoek herhalen?</target> <target>U kunt oproepen van het vergrendelingsscherm accepteren, zonder apparaat- en app-verificatie.</target> <note>No comment provided by engineer.</note> </trans-unit> - <trans-unit id="You can also connect by clicking the link. If it opens in the browser, click **Open in mobile app** button." xml:space="preserve"> - <source>You can also connect by clicking the link. If it opens in the browser, click **Open in mobile app** button.</source> - <target>U kunt ook verbinding maken door op de link te klikken. Als het in de browser wordt geopend, klikt u op de knop **Openen in mobiele app**.</target> - <note>No comment provided by engineer.</note> - </trans-unit> <trans-unit id="You can create it later" xml:space="preserve"> <source>You can create it later</source> <target>U kan het later maken</target> @@ -5685,6 +5902,11 @@ Deelnameverzoek herhalen?</target> <target>U kunt een gebruikers profiel verbergen of dempen - veeg het naar rechts.</target> <note>No comment provided by engineer.</note> </trans-unit> + <trans-unit id="You can make it visible to your SimpleX contacts via Settings." xml:space="preserve"> + <source>You can make it visible to your SimpleX contacts via Settings.</source> + <target>Je kunt het via Instellingen zichtbaar maken voor je SimpleX contacten.</target> + <note>No comment provided by engineer.</note> + </trans-unit> <trans-unit id="You can now send messages to %@" xml:space="preserve"> <source>You can now send messages to %@</source> <target>Je kunt nu berichten sturen naar %@</target> @@ -5725,6 +5947,11 @@ Deelnameverzoek herhalen?</target> <target>U kunt markdown gebruiken voor opmaak in berichten:</target> <note>No comment provided by engineer.</note> </trans-unit> + <trans-unit id="You can view invitation link again in connection details." xml:space="preserve"> + <source>You can view invitation link again in connection details.</source> + <target>U kunt de uitnodigingslink opnieuw bekijken in de verbindingsdetails.</target> + <note>No comment provided by engineer.</note> + </trans-unit> <trans-unit id="You can't send messages!" xml:space="preserve"> <source>You can't send messages!</source> <target>Je kunt geen berichten versturen!</target> @@ -5914,13 +6141,6 @@ U kunt deze verbinding verbreken en het contact verwijderen en later proberen me <target>Uw contacten kunnen volledige verwijdering van berichten toestaan.</target> <note>No comment provided by engineer.</note> </trans-unit> - <trans-unit id="Your contacts in SimpleX will see it. You can change it in Settings." xml:space="preserve"> - <source>Your contacts in SimpleX will see it. -You can change it in Settings.</source> - <target>Uw contacten in SimpleX kunnen het zien. -U kunt dit wijzigen in Instellingen.</target> - <note>No comment provided by engineer.</note> - </trans-unit> <trans-unit id="Your contacts will remain connected." xml:space="preserve"> <source>Your contacts will remain connected.</source> <target>Uw contacten blijven verbonden.</target> @@ -6073,6 +6293,16 @@ SimpleX servers kunnen uw profiel niet zien.</target> <target>geblokkeerd</target> <note>No comment provided by engineer.</note> </trans-unit> + <trans-unit id="blocked %@" xml:space="preserve"> + <source>blocked %@</source> + <target>geblokkeerd %@</target> + <note>rcv group event chat item</note> + </trans-unit> + <trans-unit id="blocked by admin" xml:space="preserve"> + <source>blocked by admin</source> + <target>geblokkeerd door beheerder</target> + <note>blocked chat item</note> + </trans-unit> <trans-unit id="bold" xml:space="preserve"> <source>bold</source> <target>vetgedrukt</target> @@ -6193,6 +6423,11 @@ SimpleX servers kunnen uw profiel niet zien.</target> <target>verbinding:%@</target> <note>connection information</note> </trans-unit> + <trans-unit id="contact %@ changed to %@" xml:space="preserve"> + <source>contact %1$@ changed to %2$@</source> + <target>contactpersoon %1$@ gewijzigd in %2$@</target> + <note>profile update event chat item</note> + </trans-unit> <trans-unit id="contact has e2e encryption" xml:space="preserve"> <source>contact has e2e encryption</source> <target>contact heeft e2e-codering</target> @@ -6463,6 +6698,11 @@ SimpleX servers kunnen uw profiel niet zien.</target> <target>lid</target> <note>member role</note> </trans-unit> + <trans-unit id="member %@ changed to %@" xml:space="preserve"> + <source>member %1$@ changed to %2$@</source> + <target>lid %1$@ gewijzigd in %2$@</target> + <note>profile update event chat item</note> + </trans-unit> <trans-unit id="member connected" xml:space="preserve"> <source>connected</source> <target>is toegetreden</target> @@ -6585,6 +6825,16 @@ SimpleX servers kunnen uw profiel niet zien.</target> <target>verwijderd %@</target> <note>rcv group event chat item</note> </trans-unit> + <trans-unit id="removed contact address" xml:space="preserve"> + <source>removed contact address</source> + <target>contactadres verwijderd</target> + <note>profile update event chat item</note> + </trans-unit> + <trans-unit id="removed profile picture" xml:space="preserve"> + <source>removed profile picture</source> + <target>profielfoto verwijderd</target> + <note>profile update event chat item</note> + </trans-unit> <trans-unit id="removed you" xml:space="preserve"> <source>removed you</source> <target>heeft je verwijderd</target> @@ -6615,6 +6865,16 @@ SimpleX servers kunnen uw profiel niet zien.</target> <target>stuur een direct bericht</target> <note>No comment provided by engineer.</note> </trans-unit> + <trans-unit id="set new contact address" xml:space="preserve"> + <source>set new contact address</source> + <target>nieuw contactadres instellen</target> + <note>profile update event chat item</note> + </trans-unit> + <trans-unit id="set new profile picture" xml:space="preserve"> + <source>set new profile picture</source> + <target>nieuwe profielfoto instellen</target> + <note>profile update event chat item</note> + </trans-unit> <trans-unit id="starting…" xml:space="preserve"> <source>starting…</source> <target>beginnen…</target> @@ -6630,16 +6890,31 @@ SimpleX servers kunnen uw profiel niet zien.</target> <target>dit contact</target> <note>notification title</note> </trans-unit> + <trans-unit id="unblocked %@" xml:space="preserve"> + <source>unblocked %@</source> + <target>gedeblokkeerd %@</target> + <note>rcv group event chat item</note> + </trans-unit> <trans-unit id="unknown" xml:space="preserve"> <source>unknown</source> <target>onbekend</target> <note>connection info</note> </trans-unit> + <trans-unit id="unknown status" xml:space="preserve"> + <source>unknown status</source> + <target>onbekende status</target> + <note>No comment provided by engineer.</note> + </trans-unit> <trans-unit id="updated group profile" xml:space="preserve"> <source>updated group profile</source> <target>bijgewerkt groep profiel</target> <note>rcv group event chat item</note> </trans-unit> + <trans-unit id="updated profile" xml:space="preserve"> + <source>updated profile</source> + <target>bijgewerkt profiel</target> + <note>profile update event chat item</note> + </trans-unit> <trans-unit id="v%@" xml:space="preserve"> <source>v%@</source> <target>v%@</target> @@ -6667,7 +6942,7 @@ SimpleX servers kunnen uw profiel niet zien.</target> </trans-unit> <trans-unit id="via relay" xml:space="preserve"> <source>via relay</source> - <target>via relais</target> + <target>via relay</target> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="video call (not e2e encrypted)" xml:space="preserve"> @@ -6710,6 +6985,11 @@ SimpleX servers kunnen uw profiel niet zien.</target> <target>jij bent waarnemer</target> <note>No comment provided by engineer.</note> </trans-unit> + <trans-unit id="you blocked %@" xml:space="preserve"> + <source>you blocked %@</source> + <target>je hebt %@ geblokkeerd</target> + <note>snd group event chat item</note> + </trans-unit> <trans-unit id="you changed address" xml:space="preserve"> <source>you changed address</source> <target>je bent van adres veranderd</target> @@ -6750,6 +7030,11 @@ SimpleX servers kunnen uw profiel niet zien.</target> <target>je hebt een eenmalige link incognito gedeeld</target> <note>chat list item description</note> </trans-unit> + <trans-unit id="you unblocked %@" xml:space="preserve"> + <source>you unblocked %@</source> + <target>je hebt %@ gedeblokkeerd</target> + <note>snd group event chat item</note> + </trans-unit> <trans-unit id="you: " xml:space="preserve"> <source>you: </source> <target>Jij: </target> diff --git a/apps/ios/SimpleX Localizations/pl.xcloc/Localized Contents/pl.xliff b/apps/ios/SimpleX Localizations/pl.xcloc/Localized Contents/pl.xliff index ad1924f4c4..94e3e8901a 100644 --- a/apps/ios/SimpleX Localizations/pl.xcloc/Localized Contents/pl.xliff +++ b/apps/ios/SimpleX Localizations/pl.xcloc/Localized Contents/pl.xliff @@ -217,6 +217,11 @@ <target>%lld wiadomości zablokowanych</target> <note>No comment provided by engineer.</note> </trans-unit> + <trans-unit id="%lld messages blocked by admin" xml:space="preserve"> + <source>%lld messages blocked by admin</source> + <target>%lld wiadomości zablokowanych przez admina</target> + <note>No comment provided by engineer.</note> + </trans-unit> <trans-unit id="%lld messages marked deleted" xml:space="preserve"> <source>%lld messages marked deleted</source> <target>%lld wiadomości oznaczonych do usunięcia</target> @@ -312,14 +317,19 @@ <target>)</target> <note>No comment provided by engineer.</note> </trans-unit> + <trans-unit id="**Add contact**: to create a new invitation link, or connect via a link you received." xml:space="preserve"> + <source>**Add contact**: to create a new invitation link, or connect via a link you received.</source> + <target>**Dodaj kontakt**: aby utworzyć nowy link z zaproszeniem lub połączyć się za pomocą otrzymanego linku.</target> + <note>No comment provided by engineer.</note> + </trans-unit> <trans-unit id="**Add new contact**: to create your one-time QR Code for your contact." xml:space="preserve"> <source>**Add new contact**: to create your one-time QR Code or link for your contact.</source> <target>**Dodaj nowy kontakt**: aby stworzyć swój jednorazowy kod QR lub link dla kontaktu.</target> <note>No comment provided by engineer.</note> </trans-unit> - <trans-unit id="**Create link / QR code** for your contact to use." xml:space="preserve"> - <source>**Create link / QR code** for your contact to use.</source> - <target>**Utwórz link / kod QR**, aby Twój kontakt mógł z niego skorzystać.</target> + <trans-unit id="**Create group**: to create a new group." xml:space="preserve"> + <source>**Create group**: to create a new group.</source> + <target>**Utwórz grupę**: aby utworzyć nową grupę.</target> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="**More private**: check new messages every 20 minutes. Device token is shared with SimpleX Chat server, but not how many contacts or messages you have." xml:space="preserve"> @@ -332,11 +342,6 @@ <target>**Najbardziej prywatny**: nie korzystaj z serwera powiadomień SimpleX Chat, sprawdzaj wiadomości okresowo w tle (zależy jak często korzystasz z aplikacji).</target> <note>No comment provided by engineer.</note> </trans-unit> - <trans-unit id="**Paste received link** or open it in the browser and tap **Open in mobile app**." xml:space="preserve"> - <source>**Paste received link** or open it in the browser and tap **Open in mobile app**.</source> - <target>**Wklej otrzymany link** lub otwórz go w przeglądarce i dotknij **Otwórz w aplikacji mobilnej**.</target> - <note>No comment provided by engineer.</note> - </trans-unit> <trans-unit id="**Please note**: you will NOT be able to recover or change passphrase if you lose it." xml:space="preserve"> <source>**Please note**: you will NOT be able to recover or change passphrase if you lose it.</source> <target>**Uwaga**: NIE będziesz w stanie odzyskać lub zmienić hasła, jeśli je stracisz.</target> @@ -347,11 +352,6 @@ <target>**Zalecane**: token urządzenia i powiadomienia są wysyłane do serwera powiadomień SimpleX Chat, ale nie treść wiadomości, rozmiar lub od kogo jest.</target> <note>No comment provided by engineer.</note> </trans-unit> - <trans-unit id="**Scan QR code**: to connect to your contact in person or via video call." xml:space="preserve"> - <source>**Scan QR code**: to connect to your contact in person or via video call.</source> - <target>**Skanuj kod QR**: aby połączyć się z kontaktem osobiście lub za pomocą połączenia wideo.</target> - <note>No comment provided by engineer.</note> - </trans-unit> <trans-unit id="**Warning**: Instant push notifications require passphrase saved in Keychain." xml:space="preserve"> <source>**Warning**: Instant push notifications require passphrase saved in Keychain.</source> <target>**Uwaga**: Natychmiastowe powiadomienia push wymagają hasła zapisanego w Keychain.</target> @@ -453,11 +453,6 @@ <target>1 tydzień</target> <note>time interval</note> </trans-unit> - <trans-unit id="1-time link" xml:space="preserve"> - <source>1-time link</source> - <target>1-razowy link</target> - <note>No comment provided by engineer.</note> - </trans-unit> <trans-unit id="5 minutes" xml:space="preserve"> <source>5 minutes</source> <target>5 minut</target> @@ -573,6 +568,11 @@ <target>Dodaj adres do swojego profilu, aby Twoje kontakty mogły go udostępnić innym osobom. Aktualizacja profilu zostanie wysłana do Twoich kontaktów.</target> <note>No comment provided by engineer.</note> </trans-unit> + <trans-unit id="Add contact" xml:space="preserve"> + <source>Add contact</source> + <target>Dodaj kontakt</target> + <note>No comment provided by engineer.</note> + </trans-unit> <trans-unit id="Add preset servers" xml:space="preserve"> <source>Add preset servers</source> <target>Dodaj gotowe serwery</target> @@ -643,6 +643,11 @@ <target>Wszyscy członkowie grupy pozostaną połączeni.</target> <note>No comment provided by engineer.</note> </trans-unit> + <trans-unit id="All messages will be deleted - this cannot be undone!" xml:space="preserve"> + <source>All messages will be deleted - this cannot be undone!</source> + <target>Wszystkie wiadomości zostaną usunięte – nie można tego cofnąć!</target> + <note>No comment provided by engineer.</note> + </trans-unit> <trans-unit id="All messages will be deleted - this cannot be undone! The messages will be deleted ONLY for you." xml:space="preserve"> <source>All messages will be deleted - this cannot be undone! The messages will be deleted ONLY for you.</source> <target>Wszystkie wiadomości zostaną usunięte - nie można tego cofnąć! Wiadomości zostaną usunięte TYLKO dla Ciebie.</target> @@ -678,9 +683,9 @@ <target>Zezwól na znikające wiadomości tylko wtedy, gdy Twój kontakt Ci na to pozwoli.</target> <note>No comment provided by engineer.</note> </trans-unit> - <trans-unit id="Allow irreversible message deletion only if your contact allows it to you." xml:space="preserve"> - <source>Allow irreversible message deletion only if your contact allows it to you.</source> - <target>Zezwalaj na nieodwracalne usuwanie wiadomości tylko wtedy, gdy Twój kontakt Ci na to pozwoli.</target> + <trans-unit id="Allow irreversible message deletion only if your contact allows it to you. (24 hours)" xml:space="preserve"> + <source>Allow irreversible message deletion only if your contact allows it to you. (24 hours)</source> + <target>Zezwalaj na nieodwracalne usuwanie wiadomości tylko wtedy, gdy Twój kontakt Ci na to pozwoli. (24 godziny)</target> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="Allow message reactions only if your contact allows them." xml:space="preserve"> @@ -703,9 +708,9 @@ <target>Zezwól na wysyłanie znikających wiadomości.</target> <note>No comment provided by engineer.</note> </trans-unit> - <trans-unit id="Allow to irreversibly delete sent messages." xml:space="preserve"> - <source>Allow to irreversibly delete sent messages.</source> - <target>Zezwól na nieodwracalne usunięcie wysłanych wiadomości.</target> + <trans-unit id="Allow to irreversibly delete sent messages. (24 hours)" xml:space="preserve"> + <source>Allow to irreversibly delete sent messages. (24 hours)</source> + <target>Zezwól na nieodwracalne usunięcie wysłanych wiadomości. (24 godziny)</target> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="Allow to send files and media." xml:space="preserve"> @@ -738,9 +743,9 @@ <target>Zezwól swoim kontaktom na połączenia do Ciebie.</target> <note>No comment provided by engineer.</note> </trans-unit> - <trans-unit id="Allow your contacts to irreversibly delete sent messages." xml:space="preserve"> - <source>Allow your contacts to irreversibly delete sent messages.</source> - <target>Zezwól swoim kontaktom na nieodwracalne usuwanie wysłanych wiadomości.</target> + <trans-unit id="Allow your contacts to irreversibly delete sent messages. (24 hours)" xml:space="preserve"> + <source>Allow your contacts to irreversibly delete sent messages. (24 hours)</source> + <target>Zezwól swoim kontaktom na nieodwracalne usuwanie wysłanych wiadomości. (24 godziny)</target> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="Allow your contacts to send disappearing messages." xml:space="preserve"> @@ -918,6 +923,11 @@ <target>Zablokuj</target> <note>No comment provided by engineer.</note> </trans-unit> + <trans-unit id="Block for all" xml:space="preserve"> + <source>Block for all</source> + <target>Zablokuj dla wszystkich</target> + <note>No comment provided by engineer.</note> + </trans-unit> <trans-unit id="Block group members" xml:space="preserve"> <source>Block group members</source> <target>Blokuj członków grupy</target> @@ -928,19 +938,29 @@ <target>Zablokuj członka</target> <note>No comment provided by engineer.</note> </trans-unit> + <trans-unit id="Block member for all?" xml:space="preserve"> + <source>Block member for all?</source> + <target>Zablokować członka dla wszystkich?</target> + <note>No comment provided by engineer.</note> + </trans-unit> <trans-unit id="Block member?" xml:space="preserve"> <source>Block member?</source> <target>Zablokować członka?</target> <note>No comment provided by engineer.</note> </trans-unit> + <trans-unit id="Blocked by admin" xml:space="preserve"> + <source>Blocked by admin</source> + <target>Zablokowany przez admina</target> + <note>No comment provided by engineer.</note> + </trans-unit> <trans-unit id="Both you and your contact can add message reactions." xml:space="preserve"> <source>Both you and your contact can add message reactions.</source> <target>Zarówno Ty, jak i Twój kontakt możecie dodawać reakcje wiadomości.</target> <note>No comment provided by engineer.</note> </trans-unit> - <trans-unit id="Both you and your contact can irreversibly delete sent messages." xml:space="preserve"> - <source>Both you and your contact can irreversibly delete sent messages.</source> - <target>Zarówno Ty, jak i Twój kontakt możecie nieodwracalnie usunąć wysłane wiadomości.</target> + <trans-unit id="Both you and your contact can irreversibly delete sent messages. (24 hours)" xml:space="preserve"> + <source>Both you and your contact can irreversibly delete sent messages. (24 hours)</source> + <target>Zarówno Ty, jak i Twój kontakt możecie nieodwracalnie usunąć wysłane wiadomości. (24 godziny)</target> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="Both you and your contact can make calls." xml:space="preserve"> @@ -978,9 +998,9 @@ <target>Połączenia</target> <note>No comment provided by engineer.</note> </trans-unit> - <trans-unit id="Can't delete user profile!" xml:space="preserve"> - <source>Can't delete user profile!</source> - <target>Nie można usunąć profilu użytkownika!</target> + <trans-unit id="Camera not available" xml:space="preserve"> + <source>Camera not available</source> + <target>Kamera nie dostępna</target> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="Can't invite contact!" xml:space="preserve"> @@ -1094,6 +1114,11 @@ <target>Czat jest zatrzymany</target> <note>No comment provided by engineer.</note> </trans-unit> + <trans-unit id="Chat is stopped. If you already used this database on another device, you should transfer it back before starting chat." xml:space="preserve"> + <source>Chat is stopped. If you already used this database on another device, you should transfer it back before starting chat.</source> + <target>Czat został zatrzymany. Jeśli korzystałeś już z tej bazy danych na innym urządzeniu, powinieneś przenieść ją z powrotem przed rozpoczęciem czatu.</target> + <note>No comment provided by engineer.</note> + </trans-unit> <trans-unit id="Chat preferences" xml:space="preserve"> <source>Chat preferences</source> <target>Preferencje czatu</target> @@ -1139,6 +1164,11 @@ <target>Wyczyścić rozmowę?</target> <note>No comment provided by engineer.</note> </trans-unit> + <trans-unit id="Clear private notes?" xml:space="preserve"> + <source>Clear private notes?</source> + <target>Wyczyścić prywatne notatki?</target> + <note>No comment provided by engineer.</note> + </trans-unit> <trans-unit id="Clear verification" xml:space="preserve"> <source>Clear verification</source> <target>Wyczyść weryfikację</target> @@ -1238,11 +1268,6 @@ To jest twój jednorazowy link!</target> <target>Połącz się przez link</target> <note>No comment provided by engineer.</note> </trans-unit> - <trans-unit id="Connect via link / QR code" xml:space="preserve"> - <source>Connect via link / QR code</source> - <target>Połącz się przez link / kod QR</target> - <note>No comment provided by engineer.</note> - </trans-unit> <trans-unit id="Connect via one-time link" xml:space="preserve"> <source>Connect via one-time link</source> <target>Połącz przez jednorazowy link</target> @@ -1418,11 +1443,6 @@ To jest twój jednorazowy link!</target> <target>Utwórz nowy profil w [aplikacji desktopowej](https://simplex.chat/downloads/). 💻</target> <note>No comment provided by engineer.</note> </trans-unit> - <trans-unit id="Create one-time invitation link" xml:space="preserve"> - <source>Create one-time invitation link</source> - <target>Utwórz jednorazowy link do zaproszenia</target> - <note>No comment provided by engineer.</note> - </trans-unit> <trans-unit id="Create profile" xml:space="preserve"> <source>Create profile</source> <target>Utwórz profil</target> @@ -1443,11 +1463,26 @@ To jest twój jednorazowy link!</target> <target>Utwórz swój profil</target> <note>No comment provided by engineer.</note> </trans-unit> + <trans-unit id="Created at" xml:space="preserve"> + <source>Created at</source> + <target>Utworzony o</target> + <note>No comment provided by engineer.</note> + </trans-unit> + <trans-unit id="Created at: %@" xml:space="preserve"> + <source>Created at: %@</source> + <target>Utworzony o: %@</target> + <note>copied message info</note> + </trans-unit> <trans-unit id="Created on %@" xml:space="preserve"> <source>Created on %@</source> <target>Utworzony w dniu %@</target> <note>No comment provided by engineer.</note> </trans-unit> + <trans-unit id="Creating link…" xml:space="preserve"> + <source>Creating link…</source> + <target>Tworzenie linku…</target> + <note>No comment provided by engineer.</note> + </trans-unit> <trans-unit id="Current Passcode" xml:space="preserve"> <source>Current Passcode</source> <target>Aktualny Pin</target> @@ -1928,6 +1963,11 @@ To nie może być cofnięte!</target> <target>Zrób to później</target> <note>No comment provided by engineer.</note> </trans-unit> + <trans-unit id="Do not send history to new members." xml:space="preserve"> + <source>Do not send history to new members.</source> + <target>Nie wysyłaj historii do nowych członków.</target> + <note>No comment provided by engineer.</note> + </trans-unit> <trans-unit id="Don't create address" xml:space="preserve"> <source>Don't create address</source> <target>Nie twórz adresu</target> @@ -1998,6 +2038,11 @@ To nie może być cofnięte!</target> <target>Czy włączyć automatyczne usuwanie wiadomości?</target> <note>No comment provided by engineer.</note> </trans-unit> + <trans-unit id="Enable camera access" xml:space="preserve"> + <source>Enable camera access</source> + <target>Włącz dostęp do kamery</target> + <note>No comment provided by engineer.</note> + </trans-unit> <trans-unit id="Enable for all" xml:space="preserve"> <source>Enable for all</source> <target>Włącz dla wszystkich</target> @@ -2063,6 +2108,11 @@ To nie może być cofnięte!</target> <target>Zaszyfrowana wiadomość lub inne zdarzenie</target> <note>notification</note> </trans-unit> + <trans-unit id="Encrypted message: app is stopped" xml:space="preserve"> + <source>Encrypted message: app is stopped</source> + <target>Zaszyfrowana wiadomość: aplikacja jest zatrzymana</target> + <note>notification</note> + </trans-unit> <trans-unit id="Encrypted message: database error" xml:space="preserve"> <source>Encrypted message: database error</source> <target>Zaszyfrowana wiadomość: błąd bazy danych</target> @@ -2208,6 +2258,11 @@ To nie może być cofnięte!</target> <target>Błąd tworzenia kontaktu członka</target> <note>No comment provided by engineer.</note> </trans-unit> + <trans-unit id="Error creating message" xml:space="preserve"> + <source>Error creating message</source> + <target>Błąd tworzenia wiadomości</target> + <note>No comment provided by engineer.</note> + </trans-unit> <trans-unit id="Error creating profile!" xml:space="preserve"> <source>Error creating profile!</source> <target>Błąd tworzenia profilu!</target> @@ -2293,6 +2348,11 @@ To nie może być cofnięte!</target> <target>Błąd ładowania %@ serwerów</target> <note>No comment provided by engineer.</note> </trans-unit> + <trans-unit id="Error opening chat" xml:space="preserve"> + <source>Error opening chat</source> + <target>Błąd otwierania czatu</target> + <note>No comment provided by engineer.</note> + </trans-unit> <trans-unit id="Error receiving file" xml:space="preserve"> <source>Error receiving file</source> <target>Błąd odbioru pliku</target> @@ -2333,6 +2393,11 @@ To nie może być cofnięte!</target> <target>Błąd zapisu hasła użytkownika</target> <note>No comment provided by engineer.</note> </trans-unit> + <trans-unit id="Error scanning code: %@" xml:space="preserve"> + <source>Error scanning code: %@</source> + <target>Błąd skanowanie kodu: %@</target> + <note>No comment provided by engineer.</note> + </trans-unit> <trans-unit id="Error sending email" xml:space="preserve"> <source>Error sending email</source> <target>Błąd wysyłania e-mail</target> @@ -2663,9 +2728,9 @@ To nie może być cofnięte!</target> <target>Członkowie grupy mogą dodawać reakcje wiadomości.</target> <note>No comment provided by engineer.</note> </trans-unit> - <trans-unit id="Group members can irreversibly delete sent messages." xml:space="preserve"> - <source>Group members can irreversibly delete sent messages.</source> - <target>Członkowie grupy mogą nieodwracalnie usuwać wysłane wiadomości.</target> + <trans-unit id="Group members can irreversibly delete sent messages. (24 hours)" xml:space="preserve"> + <source>Group members can irreversibly delete sent messages. (24 hours)</source> + <target>Członkowie grupy mogą nieodwracalnie usuwać wysłane wiadomości. (24 godziny)</target> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="Group members can send direct messages." xml:space="preserve"> @@ -2773,6 +2838,11 @@ To nie może być cofnięte!</target> <target>Historia</target> <note>No comment provided by engineer.</note> </trans-unit> + <trans-unit id="History is not sent to new members." xml:space="preserve"> + <source>History is not sent to new members.</source> + <target>Historia nie jest wysyłana do nowych członków.</target> + <note>No comment provided by engineer.</note> + </trans-unit> <trans-unit id="How SimpleX works" xml:space="preserve"> <source>How SimpleX works</source> <target>Jak działa SimpleX</target> @@ -2808,11 +2878,6 @@ To nie może być cofnięte!</target> <target>Jeśli nie możesz spotkać się osobiście, pokaż kod QR w rozmowie wideo lub udostępnij link.</target> <note>No comment provided by engineer.</note> </trans-unit> - <trans-unit id="If you cannot meet in person, you can **scan QR code in the video call**, or your contact can share an invitation link." xml:space="preserve"> - <source>If you cannot meet in person, you can **scan QR code in the video call**, or your contact can share an invitation link.</source> - <target>Jeśli nie możesz spotkać się osobiście, możesz **zeskanować kod QR w rozmowie wideo** lub Twój kontakt może udostępnić link z zaproszeniem.</target> - <note>No comment provided by engineer.</note> - </trans-unit> <trans-unit id="If you enter this passcode when opening the app, all app data will be irreversibly removed!" xml:space="preserve"> <source>If you enter this passcode when opening the app, all app data will be irreversibly removed!</source> <target>Jeśli wprowadzisz ten pin podczas otwierania aplikacji, wszystkie dane aplikacji zostaną nieodwracalnie usunięte!</target> @@ -2868,6 +2933,11 @@ To nie może być cofnięte!</target> <target>Importuj bazę danych</target> <note>No comment provided by engineer.</note> </trans-unit> + <trans-unit id="Improved message delivery" xml:space="preserve"> + <source>Improved message delivery</source> + <target>Ulepszona dostawa wiadomości</target> + <note>No comment provided by engineer.</note> + </trans-unit> <trans-unit id="Improved privacy and security" xml:space="preserve"> <source>Improved privacy and security</source> <target>Zwiększona prywatność i bezpieczeństwo</target> @@ -2970,16 +3040,36 @@ To nie może być cofnięte!</target> <target>Interfejs</target> <note>No comment provided by engineer.</note> </trans-unit> + <trans-unit id="Invalid QR code" xml:space="preserve"> + <source>Invalid QR code</source> + <target>Nieprawidłowy kod QR</target> + <note>No comment provided by engineer.</note> + </trans-unit> <trans-unit id="Invalid connection link" xml:space="preserve"> <source>Invalid connection link</source> <target>Nieprawidłowy link połączenia</target> <note>No comment provided by engineer.</note> </trans-unit> + <trans-unit id="Invalid display name!" xml:space="preserve"> + <source>Invalid display name!</source> + <target>Nieprawidłowa nazwa wyświetlana!</target> + <note>No comment provided by engineer.</note> + </trans-unit> + <trans-unit id="Invalid link" xml:space="preserve"> + <source>Invalid link</source> + <target>Nieprawidłowy link</target> + <note>No comment provided by engineer.</note> + </trans-unit> <trans-unit id="Invalid name!" xml:space="preserve"> <source>Invalid name!</source> <target>Nieprawidłowa nazwa!</target> <note>No comment provided by engineer.</note> </trans-unit> + <trans-unit id="Invalid response" xml:space="preserve"> + <source>Invalid response</source> + <target>Nieprawidłowa odpowiedź</target> + <note>No comment provided by engineer.</note> + </trans-unit> <trans-unit id="Invalid server address!" xml:space="preserve"> <source>Invalid server address!</source> <target>Nieprawidłowy adres serwera!</target> @@ -3071,6 +3161,11 @@ To nie może być cofnięte!</target> <target>Dołącz do grupy</target> <note>No comment provided by engineer.</note> </trans-unit> + <trans-unit id="Join group conversations" xml:space="preserve"> + <source>Join group conversations</source> + <target>Dołącz do grupowej rozmowy</target> + <note>No comment provided by engineer.</note> + </trans-unit> <trans-unit id="Join group?" xml:space="preserve"> <source>Join group?</source> <target>Dołączyć do grupy?</target> @@ -3098,11 +3193,21 @@ To jest twój link do grupy %@!</target> <target>Dołączanie do grupy</target> <note>No comment provided by engineer.</note> </trans-unit> + <trans-unit id="Keep" xml:space="preserve"> + <source>Keep</source> + <target>Zachowaj</target> + <note>No comment provided by engineer.</note> + </trans-unit> <trans-unit id="Keep the app open to use it from desktop" xml:space="preserve"> <source>Keep the app open to use it from desktop</source> <target>Zostaw aplikację otwartą i używaj ją z komputera</target> <note>No comment provided by engineer.</note> </trans-unit> + <trans-unit id="Keep unused invitation?" xml:space="preserve"> + <source>Keep unused invitation?</source> + <target>Zachować nieużyte zaproszenie?</target> + <note>No comment provided by engineer.</note> + </trans-unit> <trans-unit id="Keep your connections" xml:space="preserve"> <source>Keep your connections</source> <target>Zachowaj swoje połączenia</target> @@ -3188,6 +3293,11 @@ To jest twój link do grupy %@!</target> <target>Wiadomości na żywo</target> <note>No comment provided by engineer.</note> </trans-unit> + <trans-unit id="Local" xml:space="preserve"> + <source>Local</source> + <target>Lokalnie</target> + <note>No comment provided by engineer.</note> + </trans-unit> <trans-unit id="Local name" xml:space="preserve"> <source>Local name</source> <target>Nazwa lokalna</target> @@ -3428,6 +3538,11 @@ To jest twój link do grupy %@!</target> <target>Nowy Pin</target> <note>No comment provided by engineer.</note> </trans-unit> + <trans-unit id="New chat" xml:space="preserve"> + <source>New chat</source> + <target>Nowy czat</target> + <note>No comment provided by engineer.</note> + </trans-unit> <trans-unit id="New contact request" xml:space="preserve"> <source>New contact request</source> <target>Nowa prośba o kontakt</target> @@ -3552,16 +3667,16 @@ To jest twój link do grupy %@!</target> - wyłączyć członków (rola "obserwatora")</target> <note>No comment provided by engineer.</note> </trans-unit> + <trans-unit id="OK" xml:space="preserve"> + <source>OK</source> + <target>OK</target> + <note>No comment provided by engineer.</note> + </trans-unit> <trans-unit id="Off" xml:space="preserve"> <source>Off</source> <target>Wyłączony</target> <note>No comment provided by engineer.</note> </trans-unit> - <trans-unit id="Off (Local)" xml:space="preserve"> - <source>Off (Local)</source> - <target>Wyłączony (Lokalnie)</target> - <note>No comment provided by engineer.</note> - </trans-unit> <trans-unit id="Ok" xml:space="preserve"> <source>Ok</source> <target>Ok</target> @@ -3622,9 +3737,9 @@ To jest twój link do grupy %@!</target> <target>Tylko Ty możesz dodawać reakcje wiadomości.</target> <note>No comment provided by engineer.</note> </trans-unit> - <trans-unit id="Only you can irreversibly delete messages (your contact can mark them for deletion)." xml:space="preserve"> - <source>Only you can irreversibly delete messages (your contact can mark them for deletion).</source> - <target>Tylko Ty możesz nieodwracalnie usunąć wiadomości (Twój kontakt może oznaczyć je do usunięcia).</target> + <trans-unit id="Only you can irreversibly delete messages (your contact can mark them for deletion). (24 hours)" xml:space="preserve"> + <source>Only you can irreversibly delete messages (your contact can mark them for deletion). (24 hours)</source> + <target>Tylko Ty możesz nieodwracalnie usunąć wiadomości (Twój kontakt może oznaczyć je do usunięcia). (24 godziny)</target> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="Only you can make calls." xml:space="preserve"> @@ -3647,9 +3762,9 @@ To jest twój link do grupy %@!</target> <target>Tylko Twój kontakt może dodawać reakcje wiadomości.</target> <note>No comment provided by engineer.</note> </trans-unit> - <trans-unit id="Only your contact can irreversibly delete messages (you can mark them for deletion)." xml:space="preserve"> - <source>Only your contact can irreversibly delete messages (you can mark them for deletion).</source> - <target>Tylko Twój kontakt może nieodwracalnie usunąć wiadomości (możesz oznaczyć je do usunięcia).</target> + <trans-unit id="Only your contact can irreversibly delete messages (you can mark them for deletion). (24 hours)" xml:space="preserve"> + <source>Only your contact can irreversibly delete messages (you can mark them for deletion). (24 hours)</source> + <target>Tylko Twój kontakt może nieodwracalnie usunąć wiadomości (możesz oznaczyć je do usunięcia). (24 godziny)</target> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="Only your contact can make calls." xml:space="preserve"> @@ -3702,9 +3817,19 @@ To jest twój link do grupy %@!</target> <target>Otwarto źródłowy protokół i kod - każdy może uruchomić serwery.</target> <note>No comment provided by engineer.</note> </trans-unit> - <trans-unit id="Opening database…" xml:space="preserve"> - <source>Opening database…</source> - <target>Otwieranie bazy danych…</target> + <trans-unit id="Opening app…" xml:space="preserve"> + <source>Opening app…</source> + <target>Otwieranie aplikacji…</target> + <note>No comment provided by engineer.</note> + </trans-unit> + <trans-unit id="Or scan QR code" xml:space="preserve"> + <source>Or scan QR code</source> + <target>Lub zeskanuj kod QR</target> + <note>No comment provided by engineer.</note> + </trans-unit> + <trans-unit id="Or show this code" xml:space="preserve"> + <source>Or show this code</source> + <target>Lub pokaż ten kod</target> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="PING count" xml:space="preserve"> @@ -3747,10 +3872,10 @@ To jest twój link do grupy %@!</target> <target>Hasło do wyświetlenia</target> <note>No comment provided by engineer.</note> </trans-unit> - <trans-unit id="Paste" xml:space="preserve"> - <source>Paste</source> - <target>Wklej</target> - <note>No comment provided by engineer.</note> + <trans-unit id="Past member %@" xml:space="preserve"> + <source>Past member %@</source> + <target>Były członek %@</target> + <note>past/unknown group member</note> </trans-unit> <trans-unit id="Paste desktop address" xml:space="preserve"> <source>Paste desktop address</source> @@ -3762,15 +3887,15 @@ To jest twój link do grupy %@!</target> <target>Wklej obraz</target> <note>No comment provided by engineer.</note> </trans-unit> - <trans-unit id="Paste received link" xml:space="preserve"> - <source>Paste received link</source> - <target>Wklej otrzymany link</target> + <trans-unit id="Paste link to connect!" xml:space="preserve"> + <source>Paste link to connect!</source> + <target>Wklej link, aby połączyć!</target> <note>No comment provided by engineer.</note> </trans-unit> - <trans-unit id="Paste the link you received to connect with your contact." xml:space="preserve"> - <source>Paste the link you received to connect with your contact.</source> - <target>Wklej otrzymany link w pole poniżej, aby połączyć się z kontaktem.</target> - <note>placeholder</note> + <trans-unit id="Paste the link you received" xml:space="preserve"> + <source>Paste the link you received</source> + <target>Wklej link, który otrzymałeś</target> + <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="People can connect to you only via the links you share." xml:space="preserve"> <source>People can connect to you only via the links you share.</source> @@ -3807,6 +3932,13 @@ To jest twój link do grupy %@!</target> <target>Proszę sprawdzić preferencje Twoje i Twojego kontaktu.</target> <note>No comment provided by engineer.</note> </trans-unit> + <trans-unit id="Please contact developers. Error: %@" xml:space="preserve"> + <source>Please contact developers. +Error: %@</source> + <target>Proszę skontaktować się z deweloperami. +Błąd: %@</target> + <note>No comment provided by engineer.</note> + </trans-unit> <trans-unit id="Please contact group admin." xml:space="preserve"> <source>Please contact group admin.</source> <target>Skontaktuj się z administratorem grupy.</target> @@ -3892,6 +4024,11 @@ To jest twój link do grupy %@!</target> <target>Prywatne nazwy plików</target> <note>No comment provided by engineer.</note> </trans-unit> + <trans-unit id="Private notes" xml:space="preserve"> + <source>Private notes</source> + <target>Prywatne notatki</target> + <note>name of notes to self</note> + </trans-unit> <trans-unit id="Profile and server connections" xml:space="preserve"> <source>Profile and server connections</source> <target>Profil i połączenia z serwerem</target> @@ -4012,6 +4149,11 @@ To jest twój link do grupy %@!</target> <target>Przeczytaj więcej w [Podręczniku Użytkownika](https://simplex.chat/docs/guide/app-settings.html#your-simplex-contact-address).</target> <note>No comment provided by engineer.</note> </trans-unit> + <trans-unit id="Read more in [User Guide](https://simplex.chat/docs/guide/chat-profiles.html#incognito-mode)." xml:space="preserve"> + <source>Read more in [User Guide](https://simplex.chat/docs/guide/chat-profiles.html#incognito-mode).</source> + <target>Przeczytaj więcej w [Poradniku Użytkownika](https://simplex.chat/docs/guide/chat-profiles.html#incognito-mode).</target> + <note>No comment provided by engineer.</note> + </trans-unit> <trans-unit id="Read more in [User Guide](https://simplex.chat/docs/guide/readme.html#connect-to-friends)." xml:space="preserve"> <source>Read more in [User Guide](https://simplex.chat/docs/guide/readme.html#connect-to-friends).</source> <target>Przeczytaj więcej w [Podręczniku Użytkownika](https://simplex.chat/docs/guide/readme.html#connect-to-friends).</target> @@ -4067,6 +4209,11 @@ To jest twój link do grupy %@!</target> <target>Odbieranie przez</target> <note>No comment provided by engineer.</note> </trans-unit> + <trans-unit id="Recent history and improved [directory bot](simplex:/contact#/?v=1-4&smp=smp%3A%2F%2Fu2dS9sG8nMNURyZwqASV4yROM28Er0luVTx5X1CsMrU%3D%40smp4.simplex.im%2FeXSPwqTkKyDO3px4fLf1wx3MvPdjdLW3%23%2F%3Fv%3D1-2%26dh%3DMCowBQYDK2VuAyEAaiv6MkMH44L2TcYrt_CsX3ZvM11WgbMEUn0hkIKTOho%253D%26srv%3Do5vmywmrnaxalvz6wi3zicyftgio6psuvyniis6gco6bp6ekl4cqj4id.onion)." xml:space="preserve"> + <source>Recent history and improved [directory bot](simplex:/contact#/?v=1-4&smp=smp%3A%2F%2Fu2dS9sG8nMNURyZwqASV4yROM28Er0luVTx5X1CsMrU%3D%40smp4.simplex.im%2FeXSPwqTkKyDO3px4fLf1wx3MvPdjdLW3%23%2F%3Fv%3D1-2%26dh%3DMCowBQYDK2VuAyEAaiv6MkMH44L2TcYrt_CsX3ZvM11WgbMEUn0hkIKTOho%253D%26srv%3Do5vmywmrnaxalvz6wi3zicyftgio6psuvyniis6gco6bp6ekl4cqj4id.onion).</source> + <target>Ostania historia i ulepszony [bot adresowy](simplex:/contact#/?v=1-4&smp=smp%3A%2F%2Fu2dS9sG8nMNURyZwqASV4yROM28Er0luVTx5X1CsMrU%3D%40smp4.simplex.im%2FeXSPwqTkKyDO3px4fLf1wx3MvPdjdLW3%23%2F%3Fv%3D1-2%26dh%3DMCowBQYDK2VuAyEAaiv6MkMH44L2TcYrt_CsX3ZvM11WgbMEUn0hkIKTOho%253D%26srv%3Do5vmywmrnaxalvz6wi3zicyftgio6psuvyniis6gco6bp6ekl4cqj4id.onion).</target> + <note>No comment provided by engineer.</note> + </trans-unit> <trans-unit id="Recipients see updates as you type them." xml:space="preserve"> <source>Recipients see updates as you type them.</source> <target>Odbiorcy widzą aktualizacje podczas ich wpisywania.</target> @@ -4222,6 +4369,11 @@ To jest twój link do grupy %@!</target> <target>Błąd przywracania bazy danych</target> <note>No comment provided by engineer.</note> </trans-unit> + <trans-unit id="Retry" xml:space="preserve"> + <source>Retry</source> + <target>Ponów</target> + <note>No comment provided by engineer.</note> + </trans-unit> <trans-unit id="Reveal" xml:space="preserve"> <source>Reveal</source> <target>Ujawnij</target> @@ -4347,6 +4499,11 @@ To jest twój link do grupy %@!</target> <target>Zapisane serwery WebRTC ICE zostaną usunięte</target> <note>No comment provided by engineer.</note> </trans-unit> + <trans-unit id="Saved message" xml:space="preserve"> + <source>Saved message</source> + <target>Zachowano wiadomość</target> + <note>message info title</note> + </trans-unit> <trans-unit id="Scan QR code" xml:space="preserve"> <source>Scan QR code</source> <target>Zeskanuj kod QR</target> @@ -4377,6 +4534,16 @@ To jest twój link do grupy %@!</target> <target>Szukaj</target> <note>No comment provided by engineer.</note> </trans-unit> + <trans-unit id="Search bar accepts invitation links." xml:space="preserve"> + <source>Search bar accepts invitation links.</source> + <target>Pasek wyszukiwania akceptuje linki zaproszenia.</target> + <note>No comment provided by engineer.</note> + </trans-unit> + <trans-unit id="Search or paste SimpleX link" xml:space="preserve"> + <source>Search or paste SimpleX link</source> + <target>Wyszukaj lub wklej link SimpleX</target> + <note>No comment provided by engineer.</note> + </trans-unit> <trans-unit id="Secure queue" xml:space="preserve"> <source>Secure queue</source> <target>Bezpieczna kolejka</target> @@ -4482,6 +4649,11 @@ To jest twój link do grupy %@!</target> <target>Wyślij je z galerii lub niestandardowych klawiatur.</target> <note>No comment provided by engineer.</note> </trans-unit> + <trans-unit id="Send up to 100 last messages to new members." xml:space="preserve"> + <source>Send up to 100 last messages to new members.</source> + <target>Wysyłaj do 100 ostatnich wiadomości do nowych członków.</target> + <note>No comment provided by engineer.</note> + </trans-unit> <trans-unit id="Sender cancelled file transfer." xml:space="preserve"> <source>Sender cancelled file transfer.</source> <target>Nadawca anulował transfer pliku.</target> @@ -4652,9 +4824,9 @@ To jest twój link do grupy %@!</target> <target>Udostępnij link</target> <note>No comment provided by engineer.</note> </trans-unit> - <trans-unit id="Share one-time invitation link" xml:space="preserve"> - <source>Share one-time invitation link</source> - <target>Jednorazowy link zaproszenia</target> + <trans-unit id="Share this 1-time invite link" xml:space="preserve"> + <source>Share this 1-time invite link</source> + <target>Udostępnij ten jednorazowy link</target> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="Share with contacts" xml:space="preserve"> @@ -4777,16 +4949,16 @@ To jest twój link do grupy %@!</target> <target>Ktoś</target> <note>notification title</note> </trans-unit> - <trans-unit id="Start a new chat" xml:space="preserve"> - <source>Start a new chat</source> - <target>Rozpocznij nowy czat</target> - <note>No comment provided by engineer.</note> - </trans-unit> <trans-unit id="Start chat" xml:space="preserve"> <source>Start chat</source> <target>Rozpocznij czat</target> <note>No comment provided by engineer.</note> </trans-unit> + <trans-unit id="Start chat?" xml:space="preserve"> + <source>Start chat?</source> + <target>Rozpocząć czat?</target> + <note>No comment provided by engineer.</note> + </trans-unit> <trans-unit id="Start migration" xml:space="preserve"> <source>Start migration</source> <target>Rozpocznij migrację</target> @@ -4912,6 +5084,16 @@ To jest twój link do grupy %@!</target> <target>Dotnij, aby dołączyć w trybie incognito</target> <note>No comment provided by engineer.</note> </trans-unit> + <trans-unit id="Tap to paste link" xml:space="preserve"> + <source>Tap to paste link</source> + <target>Dotknij, aby wkleić link</target> + <note>No comment provided by engineer.</note> + </trans-unit> + <trans-unit id="Tap to scan" xml:space="preserve"> + <source>Tap to scan</source> + <target>Dotknij, aby zeskanować</target> + <note>No comment provided by engineer.</note> + </trans-unit> <trans-unit id="Tap to start a new chat" xml:space="preserve"> <source>Tap to start a new chat</source> <target>Dotknij, aby rozpocząć nowy czat</target> @@ -4974,6 +5156,11 @@ Może się to zdarzyć z powodu jakiegoś błędu lub gdy połączenie jest skom <target>Próba zmiany hasła bazy danych nie została zakończona.</target> <note>No comment provided by engineer.</note> </trans-unit> + <trans-unit id="The code you scanned is not a SimpleX link QR code." xml:space="preserve"> + <source>The code you scanned is not a SimpleX link QR code.</source> + <target>Kod, który zeskanowałeś nie jest kodem QR linku SimpleX.</target> + <note>No comment provided by engineer.</note> + </trans-unit> <trans-unit id="The connection you accepted will be cancelled!" xml:space="preserve"> <source>The connection you accepted will be cancelled!</source> <target>Zaakceptowane przez Ciebie połączenie zostanie anulowane!</target> @@ -5039,21 +5226,16 @@ Może się to zdarzyć z powodu jakiegoś błędu lub gdy połączenie jest skom <target>Serwery dla nowych połączeń bieżącego profilu czatu **%@**.</target> <note>No comment provided by engineer.</note> </trans-unit> + <trans-unit id="The text you pasted is not a SimpleX link." xml:space="preserve"> + <source>The text you pasted is not a SimpleX link.</source> + <target>Tekst, który wkleiłeś nie jest linkiem SimpleX.</target> + <note>No comment provided by engineer.</note> + </trans-unit> <trans-unit id="Theme" xml:space="preserve"> <source>Theme</source> <target>Motyw</target> <note>No comment provided by engineer.</note> </trans-unit> - <trans-unit id="There should be at least one user profile." xml:space="preserve"> - <source>There should be at least one user profile.</source> - <target>Powinien istnieć co najmniej jeden profil użytkownika.</target> - <note>No comment provided by engineer.</note> - </trans-unit> - <trans-unit id="There should be at least one visible user profile." xml:space="preserve"> - <source>There should be at least one visible user profile.</source> - <target>Powinien istnieć co najmniej jeden widoczny profil użytkownika.</target> - <note>No comment provided by engineer.</note> - </trans-unit> <trans-unit id="These settings are for your current profile **%@**." xml:space="preserve"> <source>These settings are for your current profile **%@**.</source> <target>Te ustawienia dotyczą Twojego bieżącego profilu **%@**.</target> @@ -5084,6 +5266,11 @@ Może się to zdarzyć z powodu jakiegoś błędu lub gdy połączenie jest skom <target>Nazwa tego urządzenia</target> <note>No comment provided by engineer.</note> </trans-unit> + <trans-unit id="This display name is invalid. Please choose another name." xml:space="preserve"> + <source>This display name is invalid. Please choose another name.</source> + <target>Nazwa wyświetlana jest nieprawidłowa. Proszę wybrać inną nazwę.</target> + <note>No comment provided by engineer.</note> + </trans-unit> <trans-unit id="This group has over %lld members, delivery receipts are not sent." xml:space="preserve"> <source>This group has over %lld members, delivery receipts are not sent.</source> <target>Ta grupa ma ponad %lld członków, potwierdzenia dostawy nie są wysyłane.</target> @@ -5186,16 +5373,16 @@ Przed włączeniem tej funkcji zostanie wyświetlony monit uwierzytelniania.</ta <target>Próbowanie połączenia z serwerem używanym do odbierania wiadomości od tego kontaktu.</target> <note>No comment provided by engineer.</note> </trans-unit> + <trans-unit id="Turkish interface" xml:space="preserve"> + <source>Turkish interface</source> + <target>Turecki interfejs</target> + <note>No comment provided by engineer.</note> + </trans-unit> <trans-unit id="Turn off" xml:space="preserve"> <source>Turn off</source> <target>Wyłącz</target> <note>No comment provided by engineer.</note> </trans-unit> - <trans-unit id="Turn off notifications?" xml:space="preserve"> - <source>Turn off notifications?</source> - <target>Wyłączyć powiadomienia?</target> - <note>No comment provided by engineer.</note> - </trans-unit> <trans-unit id="Turn on" xml:space="preserve"> <source>Turn on</source> <target>Włącz</target> @@ -5211,11 +5398,21 @@ Przed włączeniem tej funkcji zostanie wyświetlony monit uwierzytelniania.</ta <target>Odblokuj</target> <note>No comment provided by engineer.</note> </trans-unit> + <trans-unit id="Unblock for all" xml:space="preserve"> + <source>Unblock for all</source> + <target>Odblokuj dla wszystkich</target> + <note>No comment provided by engineer.</note> + </trans-unit> <trans-unit id="Unblock member" xml:space="preserve"> <source>Unblock member</source> <target>Odblokuj członka</target> <note>No comment provided by engineer.</note> </trans-unit> + <trans-unit id="Unblock member for all?" xml:space="preserve"> + <source>Unblock member for all?</source> + <target>Odblokować członka dla wszystkich?</target> + <note>No comment provided by engineer.</note> + </trans-unit> <trans-unit id="Unblock member?" xml:space="preserve"> <source>Unblock member?</source> <target>Odblokować członka?</target> @@ -5313,6 +5510,11 @@ Aby się połączyć, poproś Twój kontakt o utworzenie kolejnego linku połąc <target>Nieprzeczytane</target> <note>No comment provided by engineer.</note> </trans-unit> + <trans-unit id="Up to 100 last messages are sent to new members." xml:space="preserve"> + <source>Up to 100 last messages are sent to new members.</source> + <target>Do nowych członków wysyłanych jest do 100 ostatnich wiadomości.</target> + <note>No comment provided by engineer.</note> + </trans-unit> <trans-unit id="Update" xml:space="preserve"> <source>Update</source> <target>Aktualizuj</target> @@ -5398,6 +5600,11 @@ Aby się połączyć, poproś Twój kontakt o utworzenie kolejnego linku połąc <target>Użyj nowego profilu incognito</target> <note>No comment provided by engineer.</note> </trans-unit> + <trans-unit id="Use only local notifications?" xml:space="preserve"> + <source>Use only local notifications?</source> + <target>Używać tylko lokalnych powiadomień?</target> + <note>No comment provided by engineer.</note> + </trans-unit> <trans-unit id="Use server" xml:space="preserve"> <source>Use server</source> <target>Użyj serwera</target> @@ -5478,6 +5685,11 @@ Aby się połączyć, poproś Twój kontakt o utworzenie kolejnego linku połąc <target>Pokaż kod bezpieczeństwa</target> <note>No comment provided by engineer.</note> </trans-unit> + <trans-unit id="Visible history" xml:space="preserve"> + <source>Visible history</source> + <target>Widoczna historia</target> + <note>chat feature</note> + </trans-unit> <trans-unit id="Voice messages" xml:space="preserve"> <source>Voice messages</source> <target>Wiadomości głosowe</target> @@ -5563,11 +5775,21 @@ Aby się połączyć, poproś Twój kontakt o utworzenie kolejnego linku połąc <target>Gdy udostępnisz komuś profil incognito, będzie on używany w grupach, do których Cię zaprosi.</target> <note>No comment provided by engineer.</note> </trans-unit> + <trans-unit id="With encrypted files and media." xml:space="preserve"> + <source>With encrypted files and media.</source> + <target>Z zaszyfrowanymi plikami i multimediami.</target> + <note>No comment provided by engineer.</note> + </trans-unit> <trans-unit id="With optional welcome message." xml:space="preserve"> <source>With optional welcome message.</source> <target>Z opcjonalną wiadomością powitalną.</target> <note>No comment provided by engineer.</note> </trans-unit> + <trans-unit id="With reduced battery usage." xml:space="preserve"> + <source>With reduced battery usage.</source> + <target>Ze zmniejszonym zużyciem baterii.</target> + <note>No comment provided by engineer.</note> + </trans-unit> <trans-unit id="Wrong database passphrase" xml:space="preserve"> <source>Wrong database passphrase</source> <target>Nieprawidłowe hasło bazy danych</target> @@ -5660,11 +5882,6 @@ Powtórzyć prośbę dołączenia?</target> <target>Możesz przyjmować połączenia z ekranu blokady, bez uwierzytelniania urządzenia i aplikacji.</target> <note>No comment provided by engineer.</note> </trans-unit> - <trans-unit id="You can also connect by clicking the link. If it opens in the browser, click **Open in mobile app** button." xml:space="preserve"> - <source>You can also connect by clicking the link. If it opens in the browser, click **Open in mobile app** button.</source> - <target>Możesz też połączyć się klikając w link. Jeśli otworzy się on w przeglądarce, kliknij przycisk **Otwórz w aplikacji mobilnej**.</target> - <note>No comment provided by engineer.</note> - </trans-unit> <trans-unit id="You can create it later" xml:space="preserve"> <source>You can create it later</source> <target>Możesz go utworzyć później</target> @@ -5685,6 +5902,11 @@ Powtórzyć prośbę dołączenia?</target> <target>Możesz ukryć lub wyciszyć profil użytkownika - przesuń palcem w prawo.</target> <note>No comment provided by engineer.</note> </trans-unit> + <trans-unit id="You can make it visible to your SimpleX contacts via Settings." xml:space="preserve"> + <source>You can make it visible to your SimpleX contacts via Settings.</source> + <target>Możesz ustawić go jako widoczny dla swoich kontaktów SimpleX w Ustawieniach.</target> + <note>No comment provided by engineer.</note> + </trans-unit> <trans-unit id="You can now send messages to %@" xml:space="preserve"> <source>You can now send messages to %@</source> <target>Możesz teraz wysyłać wiadomości do %@</target> @@ -5725,6 +5947,11 @@ Powtórzyć prośbę dołączenia?</target> <target>Możesz używać markdown do formatowania wiadomości:</target> <note>No comment provided by engineer.</note> </trans-unit> + <trans-unit id="You can view invitation link again in connection details." xml:space="preserve"> + <source>You can view invitation link again in connection details.</source> + <target>Możesz zobaczyć link zaproszenia ponownie w szczegółach połączenia.</target> + <note>No comment provided by engineer.</note> + </trans-unit> <trans-unit id="You can't send messages!" xml:space="preserve"> <source>You can't send messages!</source> <target>Nie możesz wysyłać wiadomości!</target> @@ -5914,13 +6141,6 @@ Możesz anulować to połączenie i usunąć kontakt (i spróbować później z <target>Twoje kontakty mogą zezwolić na pełne usunięcie wiadomości.</target> <note>No comment provided by engineer.</note> </trans-unit> - <trans-unit id="Your contacts in SimpleX will see it. You can change it in Settings." xml:space="preserve"> - <source>Your contacts in SimpleX will see it. -You can change it in Settings.</source> - <target>Twoje kontakty w SimpleX będą to widzieć. -Możesz to zmienić w Ustawieniach.</target> - <note>No comment provided by engineer.</note> - </trans-unit> <trans-unit id="Your contacts will remain connected." xml:space="preserve"> <source>Your contacts will remain connected.</source> <target>Twoje kontakty pozostaną połączone.</target> @@ -6073,6 +6293,16 @@ Serwery SimpleX nie mogą zobaczyć Twojego profilu.</target> <target>zablokowany</target> <note>No comment provided by engineer.</note> </trans-unit> + <trans-unit id="blocked %@" xml:space="preserve"> + <source>blocked %@</source> + <target>zablokowany %@</target> + <note>rcv group event chat item</note> + </trans-unit> + <trans-unit id="blocked by admin" xml:space="preserve"> + <source>blocked by admin</source> + <target>zablokowany przez admina</target> + <note>blocked chat item</note> + </trans-unit> <trans-unit id="bold" xml:space="preserve"> <source>bold</source> <target>pogrubiona</target> @@ -6193,6 +6423,11 @@ Serwery SimpleX nie mogą zobaczyć Twojego profilu.</target> <target>połączenie: %@</target> <note>connection information</note> </trans-unit> + <trans-unit id="contact %@ changed to %@" xml:space="preserve"> + <source>contact %1$@ changed to %2$@</source> + <target>kontakt %1$@ zmieniony na %2$@</target> + <note>profile update event chat item</note> + </trans-unit> <trans-unit id="contact has e2e encryption" xml:space="preserve"> <source>contact has e2e encryption</source> <target>kontakt posiada szyfrowanie e2e</target> @@ -6463,6 +6698,11 @@ Serwery SimpleX nie mogą zobaczyć Twojego profilu.</target> <target>członek</target> <note>member role</note> </trans-unit> + <trans-unit id="member %@ changed to %@" xml:space="preserve"> + <source>member %1$@ changed to %2$@</source> + <target>członek %1$@ zmieniony na %2$@</target> + <note>profile update event chat item</note> + </trans-unit> <trans-unit id="member connected" xml:space="preserve"> <source>connected</source> <target>połączony</target> @@ -6585,6 +6825,16 @@ Serwery SimpleX nie mogą zobaczyć Twojego profilu.</target> <target>usunięto %@</target> <note>rcv group event chat item</note> </trans-unit> + <trans-unit id="removed contact address" xml:space="preserve"> + <source>removed contact address</source> + <target>usunięto adres kontaktu</target> + <note>profile update event chat item</note> + </trans-unit> + <trans-unit id="removed profile picture" xml:space="preserve"> + <source>removed profile picture</source> + <target>usunięto zdjęcie profilu</target> + <note>profile update event chat item</note> + </trans-unit> <trans-unit id="removed you" xml:space="preserve"> <source>removed you</source> <target>usunął cię</target> @@ -6615,6 +6865,16 @@ Serwery SimpleX nie mogą zobaczyć Twojego profilu.</target> <target>wyślij wiadomość bezpośrednią</target> <note>No comment provided by engineer.</note> </trans-unit> + <trans-unit id="set new contact address" xml:space="preserve"> + <source>set new contact address</source> + <target>ustaw nowy adres kontaktu</target> + <note>profile update event chat item</note> + </trans-unit> + <trans-unit id="set new profile picture" xml:space="preserve"> + <source>set new profile picture</source> + <target>ustaw nowe zdjęcie profilu</target> + <note>profile update event chat item</note> + </trans-unit> <trans-unit id="starting…" xml:space="preserve"> <source>starting…</source> <target>uruchamianie…</target> @@ -6630,16 +6890,31 @@ Serwery SimpleX nie mogą zobaczyć Twojego profilu.</target> <target>ten kontakt</target> <note>notification title</note> </trans-unit> + <trans-unit id="unblocked %@" xml:space="preserve"> + <source>unblocked %@</source> + <target>odblokowano %@</target> + <note>rcv group event chat item</note> + </trans-unit> <trans-unit id="unknown" xml:space="preserve"> <source>unknown</source> <target>nieznany</target> <note>connection info</note> </trans-unit> + <trans-unit id="unknown status" xml:space="preserve"> + <source>unknown status</source> + <target>nieznany status</target> + <note>No comment provided by engineer.</note> + </trans-unit> <trans-unit id="updated group profile" xml:space="preserve"> <source>updated group profile</source> <target>zaktualizowano profil grupy</target> <note>rcv group event chat item</note> </trans-unit> + <trans-unit id="updated profile" xml:space="preserve"> + <source>updated profile</source> + <target>zaktualizowano profil</target> + <note>profile update event chat item</note> + </trans-unit> <trans-unit id="v%@" xml:space="preserve"> <source>v%@</source> <target>v%@</target> @@ -6710,6 +6985,11 @@ Serwery SimpleX nie mogą zobaczyć Twojego profilu.</target> <target>jesteś obserwatorem</target> <note>No comment provided by engineer.</note> </trans-unit> + <trans-unit id="you blocked %@" xml:space="preserve"> + <source>you blocked %@</source> + <target>zablokowałeś %@</target> + <note>snd group event chat item</note> + </trans-unit> <trans-unit id="you changed address" xml:space="preserve"> <source>you changed address</source> <target>zmieniłeś adres</target> @@ -6750,6 +7030,11 @@ Serwery SimpleX nie mogą zobaczyć Twojego profilu.</target> <target>udostępniłeś jednorazowy link incognito</target> <note>chat list item description</note> </trans-unit> + <trans-unit id="you unblocked %@" xml:space="preserve"> + <source>you unblocked %@</source> + <target>odblokowałeś %@</target> + <note>snd group event chat item</note> + </trans-unit> <trans-unit id="you: " xml:space="preserve"> <source>you: </source> <target>ty: </target> diff --git a/apps/ios/SimpleX Localizations/ru.xcloc/Localized Contents/ru.xliff b/apps/ios/SimpleX Localizations/ru.xcloc/Localized Contents/ru.xliff index f4970446ae..b0d1a0cd24 100644 --- a/apps/ios/SimpleX Localizations/ru.xcloc/Localized Contents/ru.xliff +++ b/apps/ios/SimpleX Localizations/ru.xcloc/Localized Contents/ru.xliff @@ -217,6 +217,11 @@ <target>%lld сообщений заблокировано</target> <note>No comment provided by engineer.</note> </trans-unit> + <trans-unit id="%lld messages blocked by admin" xml:space="preserve"> + <source>%lld messages blocked by admin</source> + <target>%lld сообщений заблокировано администратором</target> + <note>No comment provided by engineer.</note> + </trans-unit> <trans-unit id="%lld messages marked deleted" xml:space="preserve"> <source>%lld messages marked deleted</source> <target>%lld сообщений помечено удалёнными</target> @@ -312,14 +317,19 @@ <target>)</target> <note>No comment provided by engineer.</note> </trans-unit> + <trans-unit id="**Add contact**: to create a new invitation link, or connect via a link you received." xml:space="preserve"> + <source>**Add contact**: to create a new invitation link, or connect via a link you received.</source> + <target>**Добавить контакт**: создать новую ссылку-приглашение или подключиться через полученную ссылку.</target> + <note>No comment provided by engineer.</note> + </trans-unit> <trans-unit id="**Add new contact**: to create your one-time QR Code for your contact." xml:space="preserve"> <source>**Add new contact**: to create your one-time QR Code or link for your contact.</source> <target>**Добавить новый контакт**: чтобы создать одноразовый QR код или ссылку для Вашего контакта.</target> <note>No comment provided by engineer.</note> </trans-unit> - <trans-unit id="**Create link / QR code** for your contact to use." xml:space="preserve"> - <source>**Create link / QR code** for your contact to use.</source> - <target>**Создать ссылку / QR код** для Вашего контакта.</target> + <trans-unit id="**Create group**: to create a new group." xml:space="preserve"> + <source>**Create group**: to create a new group.</source> + <target>**Создать группу**: создать новую группу.</target> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="**More private**: check new messages every 20 minutes. Device token is shared with SimpleX Chat server, but not how many contacts or messages you have." xml:space="preserve"> @@ -332,11 +342,6 @@ <target>**Самый конфиденциальный**: не использовать сервер уведомлений SimpleX Chat, проверять сообщения периодически в фоновом режиме (зависит от того насколько часто Вы используете приложение).</target> <note>No comment provided by engineer.</note> </trans-unit> - <trans-unit id="**Paste received link** or open it in the browser and tap **Open in mobile app**." xml:space="preserve"> - <source>**Paste received link** or open it in the browser and tap **Open in mobile app**.</source> - <target>**Вставить полученную ссылку**, или откройте её в браузере и нажмите **Open in mobile app**.</target> - <note>No comment provided by engineer.</note> - </trans-unit> <trans-unit id="**Please note**: you will NOT be able to recover or change passphrase if you lose it." xml:space="preserve"> <source>**Please note**: you will NOT be able to recover or change passphrase if you lose it.</source> <target>**Внимание**: Вы не сможете восстановить или поменять пароль, если Вы его потеряете.</target> @@ -347,11 +352,6 @@ <target>**Рекомендовано**: токен устройства и уведомления отправляются на сервер SimpleX Chat, но сервер не получает сами сообщения, их размер или от кого они.</target> <note>No comment provided by engineer.</note> </trans-unit> - <trans-unit id="**Scan QR code**: to connect to your contact in person or via video call." xml:space="preserve"> - <source>**Scan QR code**: to connect to your contact in person or via video call.</source> - <target>**Сканировать QR код**: соединиться с Вашим контактом при встрече или во время видеозвонка.</target> - <note>No comment provided by engineer.</note> - </trans-unit> <trans-unit id="**Warning**: Instant push notifications require passphrase saved in Keychain." xml:space="preserve"> <source>**Warning**: Instant push notifications require passphrase saved in Keychain.</source> <target>**Внимание**: для работы мгновенных уведомлений пароль должен быть сохранен в Keychain.</target> @@ -453,11 +453,6 @@ <target>1 неделю</target> <note>time interval</note> </trans-unit> - <trans-unit id="1-time link" xml:space="preserve"> - <source>1-time link</source> - <target>Одноразовая ссылка</target> - <note>No comment provided by engineer.</note> - </trans-unit> <trans-unit id="5 minutes" xml:space="preserve"> <source>5 minutes</source> <target>5 минут</target> @@ -573,6 +568,11 @@ <target>Добавьте адрес в свой профиль, чтобы Ваши контакты могли поделиться им. Профиль будет отправлен Вашим контактам.</target> <note>No comment provided by engineer.</note> </trans-unit> + <trans-unit id="Add contact" xml:space="preserve"> + <source>Add contact</source> + <target>Добавить контакт</target> + <note>No comment provided by engineer.</note> + </trans-unit> <trans-unit id="Add preset servers" xml:space="preserve"> <source>Add preset servers</source> <target>Добавить серверы по умолчанию</target> @@ -643,6 +643,11 @@ <target>Все члены группы, которые соединились через эту ссылку, останутся в группе.</target> <note>No comment provided by engineer.</note> </trans-unit> + <trans-unit id="All messages will be deleted - this cannot be undone!" xml:space="preserve"> + <source>All messages will be deleted - this cannot be undone!</source> + <target>Все сообщения будут удалены - это нельзя отменить!</target> + <note>No comment provided by engineer.</note> + </trans-unit> <trans-unit id="All messages will be deleted - this cannot be undone! The messages will be deleted ONLY for you." xml:space="preserve"> <source>All messages will be deleted - this cannot be undone! The messages will be deleted ONLY for you.</source> <target>Все сообщения будут удалены - это действие нельзя отменить! Сообщения будут удалены только для Вас.</target> @@ -678,9 +683,9 @@ <target>Разрешить исчезающие сообщения, только если Ваш контакт разрешает их Вам.</target> <note>No comment provided by engineer.</note> </trans-unit> - <trans-unit id="Allow irreversible message deletion only if your contact allows it to you." xml:space="preserve"> - <source>Allow irreversible message deletion only if your contact allows it to you.</source> - <target>Разрешить необратимое удаление сообщений, только если Ваш контакт разрешает это Вам.</target> + <trans-unit id="Allow irreversible message deletion only if your contact allows it to you. (24 hours)" xml:space="preserve"> + <source>Allow irreversible message deletion only if your contact allows it to you. (24 hours)</source> + <target>Разрешить необратимое удаление сообщений, только если Ваш контакт разрешает это Вам. (24 часа)</target> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="Allow message reactions only if your contact allows them." xml:space="preserve"> @@ -703,9 +708,9 @@ <target>Разрешить посылать исчезающие сообщения.</target> <note>No comment provided by engineer.</note> </trans-unit> - <trans-unit id="Allow to irreversibly delete sent messages." xml:space="preserve"> - <source>Allow to irreversibly delete sent messages.</source> - <target>Разрешить необратимо удалять отправленные сообщения.</target> + <trans-unit id="Allow to irreversibly delete sent messages. (24 hours)" xml:space="preserve"> + <source>Allow to irreversibly delete sent messages. (24 hours)</source> + <target>Разрешить необратимо удалять отправленные сообщения. (24 часа)</target> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="Allow to send files and media." xml:space="preserve"> @@ -738,9 +743,9 @@ <target>Разрешить Вашим контактам звонить Вам.</target> <note>No comment provided by engineer.</note> </trans-unit> - <trans-unit id="Allow your contacts to irreversibly delete sent messages." xml:space="preserve"> - <source>Allow your contacts to irreversibly delete sent messages.</source> - <target>Разрешить Вашим контактам необратимо удалять отправленные сообщения.</target> + <trans-unit id="Allow your contacts to irreversibly delete sent messages. (24 hours)" xml:space="preserve"> + <source>Allow your contacts to irreversibly delete sent messages. (24 hours)</source> + <target>Разрешить Вашим контактам необратимо удалять отправленные сообщения. (24 часа)</target> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="Allow your contacts to send disappearing messages." xml:space="preserve"> @@ -918,6 +923,11 @@ <target>Заблокировать</target> <note>No comment provided by engineer.</note> </trans-unit> + <trans-unit id="Block for all" xml:space="preserve"> + <source>Block for all</source> + <target>Заблокировать для всех</target> + <note>No comment provided by engineer.</note> + </trans-unit> <trans-unit id="Block group members" xml:space="preserve"> <source>Block group members</source> <target>Блокируйте членов группы</target> @@ -928,19 +938,29 @@ <target>Заблокировать члена группы</target> <note>No comment provided by engineer.</note> </trans-unit> + <trans-unit id="Block member for all?" xml:space="preserve"> + <source>Block member for all?</source> + <target>Заблокировать члена для всех?</target> + <note>No comment provided by engineer.</note> + </trans-unit> <trans-unit id="Block member?" xml:space="preserve"> <source>Block member?</source> <target>Заблокировать члена группы?</target> <note>No comment provided by engineer.</note> </trans-unit> + <trans-unit id="Blocked by admin" xml:space="preserve"> + <source>Blocked by admin</source> + <target>Заблокирован администратором</target> + <note>No comment provided by engineer.</note> + </trans-unit> <trans-unit id="Both you and your contact can add message reactions." xml:space="preserve"> <source>Both you and your contact can add message reactions.</source> <target>И Вы, и Ваш контакт можете добавлять реакции на сообщения.</target> <note>No comment provided by engineer.</note> </trans-unit> - <trans-unit id="Both you and your contact can irreversibly delete sent messages." xml:space="preserve"> - <source>Both you and your contact can irreversibly delete sent messages.</source> - <target>Вы и Ваш контакт можете необратимо удалять отправленные сообщения.</target> + <trans-unit id="Both you and your contact can irreversibly delete sent messages. (24 hours)" xml:space="preserve"> + <source>Both you and your contact can irreversibly delete sent messages. (24 hours)</source> + <target>Вы и Ваш контакт можете необратимо удалять отправленные сообщения. (24 часа)</target> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="Both you and your contact can make calls." xml:space="preserve"> @@ -978,9 +998,9 @@ <target>Звонки</target> <note>No comment provided by engineer.</note> </trans-unit> - <trans-unit id="Can't delete user profile!" xml:space="preserve"> - <source>Can't delete user profile!</source> - <target>Нельзя удалить профиль пользователя!</target> + <trans-unit id="Camera not available" xml:space="preserve"> + <source>Camera not available</source> + <target>Камера недоступна</target> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="Can't invite contact!" xml:space="preserve"> @@ -1094,6 +1114,11 @@ <target>Чат остановлен</target> <note>No comment provided by engineer.</note> </trans-unit> + <trans-unit id="Chat is stopped. If you already used this database on another device, you should transfer it back before starting chat." xml:space="preserve"> + <source>Chat is stopped. If you already used this database on another device, you should transfer it back before starting chat.</source> + <target>Чат остановлен. Если вы уже использовали эту базу данных на другом устройстве, перенесите ее обратно до запуска чата.</target> + <note>No comment provided by engineer.</note> + </trans-unit> <trans-unit id="Chat preferences" xml:space="preserve"> <source>Chat preferences</source> <target>Предпочтения</target> @@ -1139,6 +1164,11 @@ <target>Очистить разговор?</target> <note>No comment provided by engineer.</note> </trans-unit> + <trans-unit id="Clear private notes?" xml:space="preserve"> + <source>Clear private notes?</source> + <target>Очистить личные заметки?</target> + <note>No comment provided by engineer.</note> + </trans-unit> <trans-unit id="Clear verification" xml:space="preserve"> <source>Clear verification</source> <target>Сбросить подтверждение</target> @@ -1238,11 +1268,6 @@ This is your own one-time link!</source> <target>Соединиться через ссылку</target> <note>No comment provided by engineer.</note> </trans-unit> - <trans-unit id="Connect via link / QR code" xml:space="preserve"> - <source>Connect via link / QR code</source> - <target>Соединиться через ссылку / QR код</target> - <note>No comment provided by engineer.</note> - </trans-unit> <trans-unit id="Connect via one-time link" xml:space="preserve"> <source>Connect via one-time link</source> <target>Соединиться через одноразовую ссылку</target> @@ -1418,11 +1443,6 @@ This is your own one-time link!</source> <target>Создайте новый профиль в [приложении для компьютера](https://simplex.chat/downloads/). 💻</target> <note>No comment provided by engineer.</note> </trans-unit> - <trans-unit id="Create one-time invitation link" xml:space="preserve"> - <source>Create one-time invitation link</source> - <target>Создать ссылку-приглашение</target> - <note>No comment provided by engineer.</note> - </trans-unit> <trans-unit id="Create profile" xml:space="preserve"> <source>Create profile</source> <target>Создать профиль</target> @@ -1443,11 +1463,26 @@ This is your own one-time link!</source> <target>Создать профиль</target> <note>No comment provided by engineer.</note> </trans-unit> + <trans-unit id="Created at" xml:space="preserve"> + <source>Created at</source> + <target>Создано</target> + <note>No comment provided by engineer.</note> + </trans-unit> + <trans-unit id="Created at: %@" xml:space="preserve"> + <source>Created at: %@</source> + <target>Создано: %@</target> + <note>copied message info</note> + </trans-unit> <trans-unit id="Created on %@" xml:space="preserve"> <source>Created on %@</source> <target>Дата создания %@</target> <note>No comment provided by engineer.</note> </trans-unit> + <trans-unit id="Creating link…" xml:space="preserve"> + <source>Creating link…</source> + <target>Создаётся ссылка…</target> + <note>No comment provided by engineer.</note> + </trans-unit> <trans-unit id="Current Passcode" xml:space="preserve"> <source>Current Passcode</source> <target>Текущий Код</target> @@ -1928,6 +1963,11 @@ This cannot be undone!</source> <target>Отложить</target> <note>No comment provided by engineer.</note> </trans-unit> + <trans-unit id="Do not send history to new members." xml:space="preserve"> + <source>Do not send history to new members.</source> + <target>Не отправлять историю новым членам.</target> + <note>No comment provided by engineer.</note> + </trans-unit> <trans-unit id="Don't create address" xml:space="preserve"> <source>Don't create address</source> <target>Не создавать адрес</target> @@ -1998,6 +2038,11 @@ This cannot be undone!</source> <target>Включить автоматическое удаление сообщений?</target> <note>No comment provided by engineer.</note> </trans-unit> + <trans-unit id="Enable camera access" xml:space="preserve"> + <source>Enable camera access</source> + <target>Включить доступ к камере</target> + <note>No comment provided by engineer.</note> + </trans-unit> <trans-unit id="Enable for all" xml:space="preserve"> <source>Enable for all</source> <target>Включить для всех</target> @@ -2063,6 +2108,11 @@ This cannot be undone!</source> <target>Зашифрованное сообщение или событие чата</target> <note>notification</note> </trans-unit> + <trans-unit id="Encrypted message: app is stopped" xml:space="preserve"> + <source>Encrypted message: app is stopped</source> + <target>Зашифрованное сообщение: приложение остановлено</target> + <note>notification</note> + </trans-unit> <trans-unit id="Encrypted message: database error" xml:space="preserve"> <source>Encrypted message: database error</source> <target>Зашифрованное сообщение: ошибка базы данных</target> @@ -2208,6 +2258,11 @@ This cannot be undone!</source> <target>Ошибка создания контакта с членом группы</target> <note>No comment provided by engineer.</note> </trans-unit> + <trans-unit id="Error creating message" xml:space="preserve"> + <source>Error creating message</source> + <target>Ошибка создания сообщения</target> + <note>No comment provided by engineer.</note> + </trans-unit> <trans-unit id="Error creating profile!" xml:space="preserve"> <source>Error creating profile!</source> <target>Ошибка создания профиля!</target> @@ -2293,6 +2348,11 @@ This cannot be undone!</source> <target>Ошибка загрузки %@ серверов</target> <note>No comment provided by engineer.</note> </trans-unit> + <trans-unit id="Error opening chat" xml:space="preserve"> + <source>Error opening chat</source> + <target>Ошибка доступа к чату</target> + <note>No comment provided by engineer.</note> + </trans-unit> <trans-unit id="Error receiving file" xml:space="preserve"> <source>Error receiving file</source> <target>Ошибка при получении файла</target> @@ -2333,6 +2393,11 @@ This cannot be undone!</source> <target>Ошибка при сохранении пароля пользователя</target> <note>No comment provided by engineer.</note> </trans-unit> + <trans-unit id="Error scanning code: %@" xml:space="preserve"> + <source>Error scanning code: %@</source> + <target>Ошибка сканирования кода: %@</target> + <note>No comment provided by engineer.</note> + </trans-unit> <trans-unit id="Error sending email" xml:space="preserve"> <source>Error sending email</source> <target>Ошибка отправки email</target> @@ -2663,9 +2728,9 @@ This cannot be undone!</source> <target>Члены группы могут добавлять реакции на сообщения.</target> <note>No comment provided by engineer.</note> </trans-unit> - <trans-unit id="Group members can irreversibly delete sent messages." xml:space="preserve"> - <source>Group members can irreversibly delete sent messages.</source> - <target>Члены группы могут необратимо удалять отправленные сообщения.</target> + <trans-unit id="Group members can irreversibly delete sent messages. (24 hours)" xml:space="preserve"> + <source>Group members can irreversibly delete sent messages. (24 hours)</source> + <target>Члены группы могут необратимо удалять отправленные сообщения. (24 часа)</target> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="Group members can send direct messages." xml:space="preserve"> @@ -2773,6 +2838,11 @@ This cannot be undone!</source> <target>История</target> <note>No comment provided by engineer.</note> </trans-unit> + <trans-unit id="History is not sent to new members." xml:space="preserve"> + <source>History is not sent to new members.</source> + <target>История не отправляется новым членам.</target> + <note>No comment provided by engineer.</note> + </trans-unit> <trans-unit id="How SimpleX works" xml:space="preserve"> <source>How SimpleX works</source> <target>Как SimpleX работает</target> @@ -2808,11 +2878,6 @@ This cannot be undone!</source> <target>Если Вы не можете встретиться лично, покажите QR-код во время видеозвонка или поделитесь ссылкой.</target> <note>No comment provided by engineer.</note> </trans-unit> - <trans-unit id="If you cannot meet in person, you can **scan QR code in the video call**, or your contact can share an invitation link." xml:space="preserve"> - <source>If you cannot meet in person, you can **scan QR code in the video call**, or your contact can share an invitation link.</source> - <target>Если Вы не можете встретиться лично, Вы можете **сосканировать QR код во время видеозвонка**, или Ваш контакт может отправить Вам ссылку.</target> - <note>No comment provided by engineer.</note> - </trans-unit> <trans-unit id="If you enter this passcode when opening the app, all app data will be irreversibly removed!" xml:space="preserve"> <source>If you enter this passcode when opening the app, all app data will be irreversibly removed!</source> <target>Если Вы введете этот код при открытии приложения, все данные приложения будут безвозвратно удалены!</target> @@ -2868,6 +2933,11 @@ This cannot be undone!</source> <target>Импорт архива чата</target> <note>No comment provided by engineer.</note> </trans-unit> + <trans-unit id="Improved message delivery" xml:space="preserve"> + <source>Improved message delivery</source> + <target>Улучшенная доставка сообщений</target> + <note>No comment provided by engineer.</note> + </trans-unit> <trans-unit id="Improved privacy and security" xml:space="preserve"> <source>Improved privacy and security</source> <target>Улучшенная безопасность</target> @@ -2970,16 +3040,36 @@ This cannot be undone!</source> <target>Интерфейс</target> <note>No comment provided by engineer.</note> </trans-unit> + <trans-unit id="Invalid QR code" xml:space="preserve"> + <source>Invalid QR code</source> + <target>Неверный QR код</target> + <note>No comment provided by engineer.</note> + </trans-unit> <trans-unit id="Invalid connection link" xml:space="preserve"> <source>Invalid connection link</source> <target>Ошибка в ссылке контакта</target> <note>No comment provided by engineer.</note> </trans-unit> + <trans-unit id="Invalid display name!" xml:space="preserve"> + <source>Invalid display name!</source> + <target>Ошибка имени!</target> + <note>No comment provided by engineer.</note> + </trans-unit> + <trans-unit id="Invalid link" xml:space="preserve"> + <source>Invalid link</source> + <target>Ошибка ссылки</target> + <note>No comment provided by engineer.</note> + </trans-unit> <trans-unit id="Invalid name!" xml:space="preserve"> <source>Invalid name!</source> <target>Неверное имя!</target> <note>No comment provided by engineer.</note> </trans-unit> + <trans-unit id="Invalid response" xml:space="preserve"> + <source>Invalid response</source> + <target>Ошибка ответа</target> + <note>No comment provided by engineer.</note> + </trans-unit> <trans-unit id="Invalid server address!" xml:space="preserve"> <source>Invalid server address!</source> <target>Ошибка в адресе сервера!</target> @@ -3071,6 +3161,11 @@ This cannot be undone!</source> <target>Вступить в группу</target> <note>No comment provided by engineer.</note> </trans-unit> + <trans-unit id="Join group conversations" xml:space="preserve"> + <source>Join group conversations</source> + <target>Присоединяйтесь к разговорам в группах</target> + <note>No comment provided by engineer.</note> + </trans-unit> <trans-unit id="Join group?" xml:space="preserve"> <source>Join group?</source> <target>Вступить в группу?</target> @@ -3098,11 +3193,21 @@ This is your link for group %@!</source> <target>Вступление в группу</target> <note>No comment provided by engineer.</note> </trans-unit> + <trans-unit id="Keep" xml:space="preserve"> + <source>Keep</source> + <target>Оставить</target> + <note>No comment provided by engineer.</note> + </trans-unit> <trans-unit id="Keep the app open to use it from desktop" xml:space="preserve"> <source>Keep the app open to use it from desktop</source> <target>Оставьте приложение открытым, чтобы использовать его с компьютера</target> <note>No comment provided by engineer.</note> </trans-unit> + <trans-unit id="Keep unused invitation?" xml:space="preserve"> + <source>Keep unused invitation?</source> + <target>Оставить неиспользованное приглашение?</target> + <note>No comment provided by engineer.</note> + </trans-unit> <trans-unit id="Keep your connections" xml:space="preserve"> <source>Keep your connections</source> <target>Сохраните Ваши соединения</target> @@ -3188,6 +3293,11 @@ This is your link for group %@!</source> <target>"Живые" сообщения</target> <note>No comment provided by engineer.</note> </trans-unit> + <trans-unit id="Local" xml:space="preserve"> + <source>Local</source> + <target>Локальные</target> + <note>No comment provided by engineer.</note> + </trans-unit> <trans-unit id="Local name" xml:space="preserve"> <source>Local name</source> <target>Локальное имя</target> @@ -3428,6 +3538,11 @@ This is your link for group %@!</source> <target>Новый Код</target> <note>No comment provided by engineer.</note> </trans-unit> + <trans-unit id="New chat" xml:space="preserve"> + <source>New chat</source> + <target>Новый чат</target> + <note>No comment provided by engineer.</note> + </trans-unit> <trans-unit id="New contact request" xml:space="preserve"> <source>New contact request</source> <target>Новый запрос на соединение</target> @@ -3552,16 +3667,16 @@ This is your link for group %@!</source> - приостанавливать членов (роль "наблюдатель")</target> <note>No comment provided by engineer.</note> </trans-unit> + <trans-unit id="OK" xml:space="preserve"> + <source>OK</source> + <target>OK</target> + <note>No comment provided by engineer.</note> + </trans-unit> <trans-unit id="Off" xml:space="preserve"> <source>Off</source> <target>Выключено</target> <note>No comment provided by engineer.</note> </trans-unit> - <trans-unit id="Off (Local)" xml:space="preserve"> - <source>Off (Local)</source> - <target>Выключить (Локальные)</target> - <note>No comment provided by engineer.</note> - </trans-unit> <trans-unit id="Ok" xml:space="preserve"> <source>Ok</source> <target>Ок</target> @@ -3622,9 +3737,9 @@ This is your link for group %@!</source> <target>Только Вы можете добавлять реакции на сообщения.</target> <note>No comment provided by engineer.</note> </trans-unit> - <trans-unit id="Only you can irreversibly delete messages (your contact can mark them for deletion)." xml:space="preserve"> - <source>Only you can irreversibly delete messages (your contact can mark them for deletion).</source> - <target>Только Вы можете необратимо удалять сообщения (Ваш контакт может помечать их на удаление).</target> + <trans-unit id="Only you can irreversibly delete messages (your contact can mark them for deletion). (24 hours)" xml:space="preserve"> + <source>Only you can irreversibly delete messages (your contact can mark them for deletion). (24 hours)</source> + <target>Только Вы можете необратимо удалять сообщения (Ваш контакт может помечать их на удаление). (24 часа)</target> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="Only you can make calls." xml:space="preserve"> @@ -3647,9 +3762,9 @@ This is your link for group %@!</source> <target>Только Ваш контакт может добавлять реакции на сообщения.</target> <note>No comment provided by engineer.</note> </trans-unit> - <trans-unit id="Only your contact can irreversibly delete messages (you can mark them for deletion)." xml:space="preserve"> - <source>Only your contact can irreversibly delete messages (you can mark them for deletion).</source> - <target>Только Ваш контакт может необратимо удалять сообщения (Вы можете помечать их на удаление).</target> + <trans-unit id="Only your contact can irreversibly delete messages (you can mark them for deletion). (24 hours)" xml:space="preserve"> + <source>Only your contact can irreversibly delete messages (you can mark them for deletion). (24 hours)</source> + <target>Только Ваш контакт может необратимо удалять сообщения (Вы можете помечать их на удаление). (24 часа)</target> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="Only your contact can make calls." xml:space="preserve"> @@ -3702,9 +3817,19 @@ This is your link for group %@!</source> <target>Открытый протокол и код - кто угодно может запустить сервер.</target> <note>No comment provided by engineer.</note> </trans-unit> - <trans-unit id="Opening database…" xml:space="preserve"> - <source>Opening database…</source> - <target>Открытие базы данных…</target> + <trans-unit id="Opening app…" xml:space="preserve"> + <source>Opening app…</source> + <target>Приложение отрывается…</target> + <note>No comment provided by engineer.</note> + </trans-unit> + <trans-unit id="Or scan QR code" xml:space="preserve"> + <source>Or scan QR code</source> + <target>Или отсканируйте QR код</target> + <note>No comment provided by engineer.</note> + </trans-unit> + <trans-unit id="Or show this code" xml:space="preserve"> + <source>Or show this code</source> + <target>Или покажите этот код</target> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="PING count" xml:space="preserve"> @@ -3747,10 +3872,10 @@ This is your link for group %@!</source> <target>Пароль чтобы раскрыть</target> <note>No comment provided by engineer.</note> </trans-unit> - <trans-unit id="Paste" xml:space="preserve"> - <source>Paste</source> - <target>Вставить</target> - <note>No comment provided by engineer.</note> + <trans-unit id="Past member %@" xml:space="preserve"> + <source>Past member %@</source> + <target>Бывший член %@</target> + <note>past/unknown group member</note> </trans-unit> <trans-unit id="Paste desktop address" xml:space="preserve"> <source>Paste desktop address</source> @@ -3762,15 +3887,15 @@ This is your link for group %@!</source> <target>Вставить изображение</target> <note>No comment provided by engineer.</note> </trans-unit> - <trans-unit id="Paste received link" xml:space="preserve"> - <source>Paste received link</source> - <target>Вставить полученную ссылку</target> + <trans-unit id="Paste link to connect!" xml:space="preserve"> + <source>Paste link to connect!</source> + <target>Вставьте ссылку, чтобы соединиться!</target> <note>No comment provided by engineer.</note> </trans-unit> - <trans-unit id="Paste the link you received to connect with your contact." xml:space="preserve"> - <source>Paste the link you received to connect with your contact.</source> - <target>Чтобы соединиться, вставьте ссылку, полученную от Вашего контакта.</target> - <note>placeholder</note> + <trans-unit id="Paste the link you received" xml:space="preserve"> + <source>Paste the link you received</source> + <target>Вставьте полученную ссылку</target> + <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="People can connect to you only via the links you share." xml:space="preserve"> <source>People can connect to you only via the links you share.</source> @@ -3807,6 +3932,13 @@ This is your link for group %@!</source> <target>Проверьте предпочтения Вашего контакта.</target> <note>No comment provided by engineer.</note> </trans-unit> + <trans-unit id="Please contact developers. Error: %@" xml:space="preserve"> + <source>Please contact developers. +Error: %@</source> + <target>Пожалуйста, сообщите разработчикам. +Ошибка: %@</target> + <note>No comment provided by engineer.</note> + </trans-unit> <trans-unit id="Please contact group admin." xml:space="preserve"> <source>Please contact group admin.</source> <target>Пожалуйста, свяжитесь с админом группы.</target> @@ -3892,6 +4024,11 @@ This is your link for group %@!</source> <target>Защищенные имена файлов</target> <note>No comment provided by engineer.</note> </trans-unit> + <trans-unit id="Private notes" xml:space="preserve"> + <source>Private notes</source> + <target>Личные заметки</target> + <note>name of notes to self</note> + </trans-unit> <trans-unit id="Profile and server connections" xml:space="preserve"> <source>Profile and server connections</source> <target>Профиль и соединения на сервере</target> @@ -4012,6 +4149,11 @@ This is your link for group %@!</source> <target>Узнать больше в [Руководстве пользователя](https://simplex.chat/docs/guide/app-settings.html#your-simplex-contact-address).</target> <note>No comment provided by engineer.</note> </trans-unit> + <trans-unit id="Read more in [User Guide](https://simplex.chat/docs/guide/chat-profiles.html#incognito-mode)." xml:space="preserve"> + <source>Read more in [User Guide](https://simplex.chat/docs/guide/chat-profiles.html#incognito-mode).</source> + <target>Дополнительная информация в [Руководстве пользователя](https://simplex.chat/docs/guide/chat-profiles.html#incognito-mode).</target> + <note>No comment provided by engineer.</note> + </trans-unit> <trans-unit id="Read more in [User Guide](https://simplex.chat/docs/guide/readme.html#connect-to-friends)." xml:space="preserve"> <source>Read more in [User Guide](https://simplex.chat/docs/guide/readme.html#connect-to-friends).</source> <target>Узнать больше в [Руководстве пользователя](https://simplex.chat/docs/guide/readme.html#connect-to-friends).</target> @@ -4067,6 +4209,11 @@ This is your link for group %@!</source> <target>Получение через</target> <note>No comment provided by engineer.</note> </trans-unit> + <trans-unit id="Recent history and improved [directory bot](simplex:/contact#/?v=1-4&smp=smp%3A%2F%2Fu2dS9sG8nMNURyZwqASV4yROM28Er0luVTx5X1CsMrU%3D%40smp4.simplex.im%2FeXSPwqTkKyDO3px4fLf1wx3MvPdjdLW3%23%2F%3Fv%3D1-2%26dh%3DMCowBQYDK2VuAyEAaiv6MkMH44L2TcYrt_CsX3ZvM11WgbMEUn0hkIKTOho%253D%26srv%3Do5vmywmrnaxalvz6wi3zicyftgio6psuvyniis6gco6bp6ekl4cqj4id.onion)." xml:space="preserve"> + <source>Recent history and improved [directory bot](simplex:/contact#/?v=1-4&smp=smp%3A%2F%2Fu2dS9sG8nMNURyZwqASV4yROM28Er0luVTx5X1CsMrU%3D%40smp4.simplex.im%2FeXSPwqTkKyDO3px4fLf1wx3MvPdjdLW3%23%2F%3Fv%3D1-2%26dh%3DMCowBQYDK2VuAyEAaiv6MkMH44L2TcYrt_CsX3ZvM11WgbMEUn0hkIKTOho%253D%26srv%3Do5vmywmrnaxalvz6wi3zicyftgio6psuvyniis6gco6bp6ekl4cqj4id.onion).</source> + <target>История сообщений и улучшенный [каталог групп](simplex:/contact#/?v=1-4&smp=smp%3A%2F%2Fu2dS9sG8nMNURyZwqASV4yROM28Er0luVTx5X1CsMrU%3D%40smp4.simplex.im%2FeXSPwqTkKyDO3px4fLf1wx3MvPdjdLW3%23%2F%3Fv%3D1-2%26dh%3DMCowBQYDK2VuAyEAaiv6MkMH44L2TcYrt_CsX3ZvM11WgbMEUn0hkIKTOho%253D%26srv%3Do5vmywmrnaxalvz6wi3zicyftgio6psuvyniis6gco6bp6ekl4cqj4id.onion).</target> + <note>No comment provided by engineer.</note> + </trans-unit> <trans-unit id="Recipients see updates as you type them." xml:space="preserve"> <source>Recipients see updates as you type them.</source> <target>Получатели видят их в то время как Вы их набираете.</target> @@ -4222,6 +4369,11 @@ This is your link for group %@!</source> <target>Ошибка при восстановлении базы данных</target> <note>No comment provided by engineer.</note> </trans-unit> + <trans-unit id="Retry" xml:space="preserve"> + <source>Retry</source> + <target>Повторить</target> + <note>No comment provided by engineer.</note> + </trans-unit> <trans-unit id="Reveal" xml:space="preserve"> <source>Reveal</source> <target>Показать</target> @@ -4347,6 +4499,11 @@ This is your link for group %@!</source> <target>Сохраненные WebRTC ICE серверы будут удалены</target> <note>No comment provided by engineer.</note> </trans-unit> + <trans-unit id="Saved message" xml:space="preserve"> + <source>Saved message</source> + <target>Сохраненное сообщение</target> + <note>message info title</note> + </trans-unit> <trans-unit id="Scan QR code" xml:space="preserve"> <source>Scan QR code</source> <target>Сканировать QR код</target> @@ -4377,6 +4534,16 @@ This is your link for group %@!</source> <target>Поиск</target> <note>No comment provided by engineer.</note> </trans-unit> + <trans-unit id="Search bar accepts invitation links." xml:space="preserve"> + <source>Search bar accepts invitation links.</source> + <target>Поле поиска поддерживает ссылки-приглашения.</target> + <note>No comment provided by engineer.</note> + </trans-unit> + <trans-unit id="Search or paste SimpleX link" xml:space="preserve"> + <source>Search or paste SimpleX link</source> + <target>Искать или вставьте ссылку SimpleX</target> + <note>No comment provided by engineer.</note> + </trans-unit> <trans-unit id="Secure queue" xml:space="preserve"> <source>Secure queue</source> <target>Защита очереди</target> @@ -4482,6 +4649,11 @@ This is your link for group %@!</source> <target>Отправьте из галереи или из дополнительных клавиатур.</target> <note>No comment provided by engineer.</note> </trans-unit> + <trans-unit id="Send up to 100 last messages to new members." xml:space="preserve"> + <source>Send up to 100 last messages to new members.</source> + <target>Отправить до 100 последних сообщений новым членам.</target> + <note>No comment provided by engineer.</note> + </trans-unit> <trans-unit id="Sender cancelled file transfer." xml:space="preserve"> <source>Sender cancelled file transfer.</source> <target>Отправитель отменил передачу файла.</target> @@ -4652,9 +4824,9 @@ This is your link for group %@!</source> <target>Поделиться ссылкой</target> <note>No comment provided by engineer.</note> </trans-unit> - <trans-unit id="Share one-time invitation link" xml:space="preserve"> - <source>Share one-time invitation link</source> - <target>Поделиться ссылкой-приглашением</target> + <trans-unit id="Share this 1-time invite link" xml:space="preserve"> + <source>Share this 1-time invite link</source> + <target>Поделиться одноразовой ссылкой-приглашением</target> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="Share with contacts" xml:space="preserve"> @@ -4777,16 +4949,16 @@ This is your link for group %@!</source> <target>Контакт</target> <note>notification title</note> </trans-unit> - <trans-unit id="Start a new chat" xml:space="preserve"> - <source>Start a new chat</source> - <target>Начать новый разговор</target> - <note>No comment provided by engineer.</note> - </trans-unit> <trans-unit id="Start chat" xml:space="preserve"> <source>Start chat</source> <target>Запустить чат</target> <note>No comment provided by engineer.</note> </trans-unit> + <trans-unit id="Start chat?" xml:space="preserve"> + <source>Start chat?</source> + <target>Запустить чат?</target> + <note>No comment provided by engineer.</note> + </trans-unit> <trans-unit id="Start migration" xml:space="preserve"> <source>Start migration</source> <target>Запустить перемещение данных</target> @@ -4912,6 +5084,16 @@ This is your link for group %@!</source> <target>Нажмите, чтобы вступить инкогнито</target> <note>No comment provided by engineer.</note> </trans-unit> + <trans-unit id="Tap to paste link" xml:space="preserve"> + <source>Tap to paste link</source> + <target>Нажмите, чтобы вставить ссылку</target> + <note>No comment provided by engineer.</note> + </trans-unit> + <trans-unit id="Tap to scan" xml:space="preserve"> + <source>Tap to scan</source> + <target>Нажмите, чтобы сканировать</target> + <note>No comment provided by engineer.</note> + </trans-unit> <trans-unit id="Tap to start a new chat" xml:space="preserve"> <source>Tap to start a new chat</source> <target>Нажмите, чтобы начать чат</target> @@ -4974,6 +5156,11 @@ It can happen because of some bug or when the connection is compromised.</source <target>Попытка поменять пароль базы данных не была завершена.</target> <note>No comment provided by engineer.</note> </trans-unit> + <trans-unit id="The code you scanned is not a SimpleX link QR code." xml:space="preserve"> + <source>The code you scanned is not a SimpleX link QR code.</source> + <target>Этот QR код не является SimpleX-ccылкой.</target> + <note>No comment provided by engineer.</note> + </trans-unit> <trans-unit id="The connection you accepted will be cancelled!" xml:space="preserve"> <source>The connection you accepted will be cancelled!</source> <target>Подтвержденное соединение будет отменено!</target> @@ -5039,21 +5226,16 @@ It can happen because of some bug or when the connection is compromised.</source <target>Серверы для новых соединений Вашего текущего профиля чата **%@**.</target> <note>No comment provided by engineer.</note> </trans-unit> + <trans-unit id="The text you pasted is not a SimpleX link." xml:space="preserve"> + <source>The text you pasted is not a SimpleX link.</source> + <target>Вставленный текст не является SimpleX-ссылкой.</target> + <note>No comment provided by engineer.</note> + </trans-unit> <trans-unit id="Theme" xml:space="preserve"> <source>Theme</source> <target>Тема</target> <note>No comment provided by engineer.</note> </trans-unit> - <trans-unit id="There should be at least one user profile." xml:space="preserve"> - <source>There should be at least one user profile.</source> - <target>Должен быть хотя бы один профиль пользователя.</target> - <note>No comment provided by engineer.</note> - </trans-unit> - <trans-unit id="There should be at least one visible user profile." xml:space="preserve"> - <source>There should be at least one visible user profile.</source> - <target>Должен быть хотя бы один открытый профиль пользователя.</target> - <note>No comment provided by engineer.</note> - </trans-unit> <trans-unit id="These settings are for your current profile **%@**." xml:space="preserve"> <source>These settings are for your current profile **%@**.</source> <target>Установки для Вашего активного профиля **%@**.</target> @@ -5084,6 +5266,11 @@ It can happen because of some bug or when the connection is compromised.</source <target>Имя этого устройства</target> <note>No comment provided by engineer.</note> </trans-unit> + <trans-unit id="This display name is invalid. Please choose another name." xml:space="preserve"> + <source>This display name is invalid. Please choose another name.</source> + <target>Ошибка имени профиля. Пожалуйста, выберите другое имя.</target> + <note>No comment provided by engineer.</note> + </trans-unit> <trans-unit id="This group has over %lld members, delivery receipts are not sent." xml:space="preserve"> <source>This group has over %lld members, delivery receipts are not sent.</source> <target>В группе более %lld членов, отчёты о доставке выключены.</target> @@ -5186,16 +5373,16 @@ You will be prompted to complete authentication before this feature is enabled.< <target>Устанавливается соединение с сервером, через который Вы получаете сообщения от этого контакта.</target> <note>No comment provided by engineer.</note> </trans-unit> + <trans-unit id="Turkish interface" xml:space="preserve"> + <source>Turkish interface</source> + <target>Турецкий интерфейс</target> + <note>No comment provided by engineer.</note> + </trans-unit> <trans-unit id="Turn off" xml:space="preserve"> <source>Turn off</source> <target>Выключить</target> <note>No comment provided by engineer.</note> </trans-unit> - <trans-unit id="Turn off notifications?" xml:space="preserve"> - <source>Turn off notifications?</source> - <target>Выключить уведомления?</target> - <note>No comment provided by engineer.</note> - </trans-unit> <trans-unit id="Turn on" xml:space="preserve"> <source>Turn on</source> <target>Включить</target> @@ -5211,11 +5398,21 @@ You will be prompted to complete authentication before this feature is enabled.< <target>Разблокировать</target> <note>No comment provided by engineer.</note> </trans-unit> + <trans-unit id="Unblock for all" xml:space="preserve"> + <source>Unblock for all</source> + <target>Разблокировать для всех</target> + <note>No comment provided by engineer.</note> + </trans-unit> <trans-unit id="Unblock member" xml:space="preserve"> <source>Unblock member</source> <target>Разблокировать члена группы</target> <note>No comment provided by engineer.</note> </trans-unit> + <trans-unit id="Unblock member for all?" xml:space="preserve"> + <source>Unblock member for all?</source> + <target>Разблокировать члена для всех?</target> + <note>No comment provided by engineer.</note> + </trans-unit> <trans-unit id="Unblock member?" xml:space="preserve"> <source>Unblock member?</source> <target>Разблокировать члена группы?</target> @@ -5313,6 +5510,11 @@ To connect, please ask your contact to create another connection link and check <target>Не прочитано</target> <note>No comment provided by engineer.</note> </trans-unit> + <trans-unit id="Up to 100 last messages are sent to new members." xml:space="preserve"> + <source>Up to 100 last messages are sent to new members.</source> + <target>До 100 последних сообщений отправляются новым членам.</target> + <note>No comment provided by engineer.</note> + </trans-unit> <trans-unit id="Update" xml:space="preserve"> <source>Update</source> <target>Обновить</target> @@ -5398,6 +5600,11 @@ To connect, please ask your contact to create another connection link and check <target>Использовать новый Инкогнито профиль</target> <note>No comment provided by engineer.</note> </trans-unit> + <trans-unit id="Use only local notifications?" xml:space="preserve"> + <source>Use only local notifications?</source> + <target>Использовать только локальные нотификации?</target> + <note>No comment provided by engineer.</note> + </trans-unit> <trans-unit id="Use server" xml:space="preserve"> <source>Use server</source> <target>Использовать сервер</target> @@ -5478,6 +5685,11 @@ To connect, please ask your contact to create another connection link and check <target>Показать код безопасности</target> <note>No comment provided by engineer.</note> </trans-unit> + <trans-unit id="Visible history" xml:space="preserve"> + <source>Visible history</source> + <target>Доступ к истории</target> + <note>chat feature</note> + </trans-unit> <trans-unit id="Voice messages" xml:space="preserve"> <source>Voice messages</source> <target>Голосовые сообщения</target> @@ -5563,11 +5775,21 @@ To connect, please ask your contact to create another connection link and check <target>Когда Вы соединены с контактом инкогнито, тот же самый инкогнито профиль будет использоваться для групп с этим контактом.</target> <note>No comment provided by engineer.</note> </trans-unit> + <trans-unit id="With encrypted files and media." xml:space="preserve"> + <source>With encrypted files and media.</source> + <target>С зашифрованными файлами и медиа.</target> + <note>No comment provided by engineer.</note> + </trans-unit> <trans-unit id="With optional welcome message." xml:space="preserve"> <source>With optional welcome message.</source> <target>С опциональным авто-ответом.</target> <note>No comment provided by engineer.</note> </trans-unit> + <trans-unit id="With reduced battery usage." xml:space="preserve"> + <source>With reduced battery usage.</source> + <target>С уменьшенным потреблением батареи.</target> + <note>No comment provided by engineer.</note> + </trans-unit> <trans-unit id="Wrong database passphrase" xml:space="preserve"> <source>Wrong database passphrase</source> <target>Неправильный пароль базы данных</target> @@ -5660,11 +5882,6 @@ Repeat join request?</source> <target>Вы можете принимать звонки на экране блокировки, без аутентификации.</target> <note>No comment provided by engineer.</note> </trans-unit> - <trans-unit id="You can also connect by clicking the link. If it opens in the browser, click **Open in mobile app** button." xml:space="preserve"> - <source>You can also connect by clicking the link. If it opens in the browser, click **Open in mobile app** button.</source> - <target>Вы также можете соединиться, открыв ссылку. Если ссылка откроется в браузере, нажмите кнопку **Open in mobile app**.</target> - <note>No comment provided by engineer.</note> - </trans-unit> <trans-unit id="You can create it later" xml:space="preserve"> <source>You can create it later</source> <target>Вы можете создать его позже</target> @@ -5685,6 +5902,11 @@ Repeat join request?</source> <target>Вы можете скрыть профиль или выключить уведомления - потяните его вправо.</target> <note>No comment provided by engineer.</note> </trans-unit> + <trans-unit id="You can make it visible to your SimpleX contacts via Settings." xml:space="preserve"> + <source>You can make it visible to your SimpleX contacts via Settings.</source> + <target>Вы можете сделать его видимым для ваших контактов в SimpleX через Настройки.</target> + <note>No comment provided by engineer.</note> + </trans-unit> <trans-unit id="You can now send messages to %@" xml:space="preserve"> <source>You can now send messages to %@</source> <target>Вы теперь можете отправлять сообщения %@</target> @@ -5725,6 +5947,11 @@ Repeat join request?</source> <target>Вы можете форматировать сообщения:</target> <note>No comment provided by engineer.</note> </trans-unit> + <trans-unit id="You can view invitation link again in connection details." xml:space="preserve"> + <source>You can view invitation link again in connection details.</source> + <target>Вы можете увидеть ссылку-приглашение снова открыв соединение.</target> + <note>No comment provided by engineer.</note> + </trans-unit> <trans-unit id="You can't send messages!" xml:space="preserve"> <source>You can't send messages!</source> <target>Вы не можете отправлять сообщения!</target> @@ -5914,13 +6141,6 @@ You can cancel this connection and remove the contact (and try later with a new <target>Ваши контакты могут разрешить окончательное удаление сообщений.</target> <note>No comment provided by engineer.</note> </trans-unit> - <trans-unit id="Your contacts in SimpleX will see it. You can change it in Settings." xml:space="preserve"> - <source>Your contacts in SimpleX will see it. -You can change it in Settings.</source> - <target>Ваши контакты в SimpleX получат этот адрес. -Вы можете изменить это в Настройках.</target> - <note>No comment provided by engineer.</note> - </trans-unit> <trans-unit id="Your contacts will remain connected." xml:space="preserve"> <source>Your contacts will remain connected.</source> <target>Ваши контакты сохранятся.</target> @@ -6073,6 +6293,16 @@ SimpleX серверы не могут получить доступ к Ваше <target>заблокировано</target> <note>No comment provided by engineer.</note> </trans-unit> + <trans-unit id="blocked %@" xml:space="preserve"> + <source>blocked %@</source> + <target>%@ заблокирован</target> + <note>rcv group event chat item</note> + </trans-unit> + <trans-unit id="blocked by admin" xml:space="preserve"> + <source>blocked by admin</source> + <target>заблокировано администратором</target> + <note>blocked chat item</note> + </trans-unit> <trans-unit id="bold" xml:space="preserve"> <source>bold</source> <target>жирный</target> @@ -6193,6 +6423,11 @@ SimpleX серверы не могут получить доступ к Ваше <target>connection:%@</target> <note>connection information</note> </trans-unit> + <trans-unit id="contact %@ changed to %@" xml:space="preserve"> + <source>contact %1$@ changed to %2$@</source> + <target>контакт %1$@ изменён на %2$@</target> + <note>profile update event chat item</note> + </trans-unit> <trans-unit id="contact has e2e encryption" xml:space="preserve"> <source>contact has e2e encryption</source> <target>у контакта есть e2e шифрование</target> @@ -6463,6 +6698,11 @@ SimpleX серверы не могут получить доступ к Ваше <target>член группы</target> <note>member role</note> </trans-unit> + <trans-unit id="member %@ changed to %@" xml:space="preserve"> + <source>member %1$@ changed to %2$@</source> + <target>член %1$@ изменился на %2$@</target> + <note>profile update event chat item</note> + </trans-unit> <trans-unit id="member connected" xml:space="preserve"> <source>connected</source> <target>соединен(а)</target> @@ -6585,6 +6825,16 @@ SimpleX серверы не могут получить доступ к Ваше <target>удалил(а) %@</target> <note>rcv group event chat item</note> </trans-unit> + <trans-unit id="removed contact address" xml:space="preserve"> + <source>removed contact address</source> + <target>удалён адрес контакта</target> + <note>profile update event chat item</note> + </trans-unit> + <trans-unit id="removed profile picture" xml:space="preserve"> + <source>removed profile picture</source> + <target>удалена картинка профиля</target> + <note>profile update event chat item</note> + </trans-unit> <trans-unit id="removed you" xml:space="preserve"> <source>removed you</source> <target>удалил(а) Вас из группы</target> @@ -6615,6 +6865,16 @@ SimpleX серверы не могут получить доступ к Ваше <target>отправьте сообщение</target> <note>No comment provided by engineer.</note> </trans-unit> + <trans-unit id="set new contact address" xml:space="preserve"> + <source>set new contact address</source> + <target>установлен новый адрес контакта</target> + <note>profile update event chat item</note> + </trans-unit> + <trans-unit id="set new profile picture" xml:space="preserve"> + <source>set new profile picture</source> + <target>установлена новая картинка профиля</target> + <note>profile update event chat item</note> + </trans-unit> <trans-unit id="starting…" xml:space="preserve"> <source>starting…</source> <target>инициализация…</target> @@ -6630,16 +6890,31 @@ SimpleX серверы не могут получить доступ к Ваше <target>этот контакт</target> <note>notification title</note> </trans-unit> + <trans-unit id="unblocked %@" xml:space="preserve"> + <source>unblocked %@</source> + <target>%@ разблокирован</target> + <note>rcv group event chat item</note> + </trans-unit> <trans-unit id="unknown" xml:space="preserve"> <source>unknown</source> <target>неизвестно</target> <note>connection info</note> </trans-unit> + <trans-unit id="unknown status" xml:space="preserve"> + <source>unknown status</source> + <target>неизвестный статус</target> + <note>No comment provided by engineer.</note> + </trans-unit> <trans-unit id="updated group profile" xml:space="preserve"> <source>updated group profile</source> <target>обновил(а) профиль группы</target> <note>rcv group event chat item</note> </trans-unit> + <trans-unit id="updated profile" xml:space="preserve"> + <source>updated profile</source> + <target>профиль обновлён</target> + <note>profile update event chat item</note> + </trans-unit> <trans-unit id="v%@" xml:space="preserve"> <source>v%@</source> <target>v%@</target> @@ -6710,6 +6985,11 @@ SimpleX серверы не могут получить доступ к Ваше <target>только чтение сообщений</target> <note>No comment provided by engineer.</note> </trans-unit> + <trans-unit id="you blocked %@" xml:space="preserve"> + <source>you blocked %@</source> + <target>Вы заблокировали %@</target> + <note>snd group event chat item</note> + </trans-unit> <trans-unit id="you changed address" xml:space="preserve"> <source>you changed address</source> <target>Вы поменяли адрес</target> @@ -6750,6 +7030,11 @@ SimpleX серверы не могут получить доступ к Ваше <target>Вы создали ссылку инкогнито</target> <note>chat list item description</note> </trans-unit> + <trans-unit id="you unblocked %@" xml:space="preserve"> + <source>you unblocked %@</source> + <target>Вы разблокировали %@</target> + <note>snd group event chat item</note> + </trans-unit> <trans-unit id="you: " xml:space="preserve"> <source>you: </source> <target>Вы: </target> diff --git a/apps/ios/SimpleX Localizations/th.xcloc/Localized Contents/th.xliff b/apps/ios/SimpleX Localizations/th.xcloc/Localized Contents/th.xliff index bcb39e6e03..5e0659e935 100644 --- a/apps/ios/SimpleX Localizations/th.xcloc/Localized Contents/th.xliff +++ b/apps/ios/SimpleX Localizations/th.xcloc/Localized Contents/th.xliff @@ -207,6 +207,10 @@ <source>%lld messages blocked</source> <note>No comment provided by engineer.</note> </trans-unit> + <trans-unit id="%lld messages blocked by admin" xml:space="preserve"> + <source>%lld messages blocked by admin</source> + <note>No comment provided by engineer.</note> + </trans-unit> <trans-unit id="%lld messages marked deleted" xml:space="preserve"> <source>%lld messages marked deleted</source> <note>No comment provided by engineer.</note> @@ -297,14 +301,17 @@ <target>)</target> <note>No comment provided by engineer.</note> </trans-unit> + <trans-unit id="**Add contact**: to create a new invitation link, or connect via a link you received." xml:space="preserve"> + <source>**Add contact**: to create a new invitation link, or connect via a link you received.</source> + <note>No comment provided by engineer.</note> + </trans-unit> <trans-unit id="**Add new contact**: to create your one-time QR Code for your contact." xml:space="preserve"> <source>**Add new contact**: to create your one-time QR Code or link for your contact.</source> <target>**เพิ่มผู้ติดต่อใหม่**: เพื่อสร้างคิวอาร์โค้ดแบบใช้ครั้งเดียวหรือลิงก์สำหรับผู้ติดต่อของคุณ</target> <note>No comment provided by engineer.</note> </trans-unit> - <trans-unit id="**Create link / QR code** for your contact to use." xml:space="preserve"> - <source>**Create link / QR code** for your contact to use.</source> - <target>**สร้างลิงค์ / คิวอาร์โค้ด** เพื่อให้ผู้ติดต่อของคุณใช้</target> + <trans-unit id="**Create group**: to create a new group." xml:space="preserve"> + <source>**Create group**: to create a new group.</source> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="**More private**: check new messages every 20 minutes. Device token is shared with SimpleX Chat server, but not how many contacts or messages you have." xml:space="preserve"> @@ -317,11 +324,6 @@ <target>**ส่วนตัวที่สุด**: ไม่ใช้เซิร์ฟเวอร์การแจ้งเตือนของ SimpleX Chat ตรวจสอบข้อความเป็นระยะในพื้นหลัง (ขึ้นอยู่กับความถี่ที่คุณใช้แอป)</target> <note>No comment provided by engineer.</note> </trans-unit> - <trans-unit id="**Paste received link** or open it in the browser and tap **Open in mobile app**." xml:space="preserve"> - <source>**Paste received link** or open it in the browser and tap **Open in mobile app**.</source> - <target>**แปะลิงก์ที่ได้รับ** หรือเปิดในเบราว์เซอร์แล้วแตะ **เปิดในแอปมือถือ**</target> - <note>No comment provided by engineer.</note> - </trans-unit> <trans-unit id="**Please note**: you will NOT be able to recover or change passphrase if you lose it." xml:space="preserve"> <source>**Please note**: you will NOT be able to recover or change passphrase if you lose it.</source> <target>**โปรดทราบ**: คุณจะไม่สามารถกู้คืนหรือเปลี่ยนรหัสผ่านได้หากคุณทำรหัสผ่านหาย</target> @@ -332,11 +334,6 @@ <target>**แนะนำ**: โทเค็นอุปกรณ์และการแจ้งเตือนจะถูกส่งไปยังเซิร์ฟเวอร์การแจ้งเตือนของ SimpleX Chat แต่ไม่ใช่เนื้อหาข้อความ ขนาด หรือผู้ที่ส่ง</target> <note>No comment provided by engineer.</note> </trans-unit> - <trans-unit id="**Scan QR code**: to connect to your contact in person or via video call." xml:space="preserve"> - <source>**Scan QR code**: to connect to your contact in person or via video call.</source> - <target>**สแกนคิวอาร์โค้ด**: เพื่อเชื่อมต่อกับผู้ติดต่อของคุณด้วยตนเองหรือผ่านการสนทนาทางวิดีโอ</target> - <note>No comment provided by engineer.</note> - </trans-unit> <trans-unit id="**Warning**: Instant push notifications require passphrase saved in Keychain." xml:space="preserve"> <source>**Warning**: Instant push notifications require passphrase saved in Keychain.</source> <target>**คำเตือน**: การแจ้งเตือนแบบพุชทันทีจำเป็นต้องบันทึกรหัสผ่านไว้ใน Keychain</target> @@ -431,11 +428,6 @@ <target>1 สัปดาห์</target> <note>time interval</note> </trans-unit> - <trans-unit id="1-time link" xml:space="preserve"> - <source>1-time link</source> - <target>ลิงก์สำหรับใช้ 1 ครั้ง</target> - <note>No comment provided by engineer.</note> - </trans-unit> <trans-unit id="5 minutes" xml:space="preserve"> <source>5 minutes</source> <target>5 นาที</target> @@ -549,6 +541,10 @@ <target>เพิ่มที่อยู่ลงในโปรไฟล์ของคุณ เพื่อให้ผู้ติดต่อของคุณสามารถแชร์กับผู้อื่นได้ การอัปเดตโปรไฟล์จะถูกส่งไปยังผู้ติดต่อของคุณ</target> <note>No comment provided by engineer.</note> </trans-unit> + <trans-unit id="Add contact" xml:space="preserve"> + <source>Add contact</source> + <note>No comment provided by engineer.</note> + </trans-unit> <trans-unit id="Add preset servers" xml:space="preserve"> <source>Add preset servers</source> <target>เพิ่มเซิร์ฟเวอร์ที่ตั้งไว้ล่วงหน้า</target> @@ -619,6 +615,10 @@ <target>สมาชิกในกลุ่มทุกคนจะยังคงเชื่อมต่ออยู่.</target> <note>No comment provided by engineer.</note> </trans-unit> + <trans-unit id="All messages will be deleted - this cannot be undone!" xml:space="preserve"> + <source>All messages will be deleted - this cannot be undone!</source> + <note>No comment provided by engineer.</note> + </trans-unit> <trans-unit id="All messages will be deleted - this cannot be undone! The messages will be deleted ONLY for you." xml:space="preserve"> <source>All messages will be deleted - this cannot be undone! The messages will be deleted ONLY for you.</source> <target>ข้อความทั้งหมดจะถูกลบ - ไม่สามารถยกเลิกได้! ข้อความจะถูกลบสำหรับคุณเท่านั้น.</target> @@ -653,8 +653,8 @@ <target>อนุญาตให้ข้อความที่หายไปเฉพาะในกรณีที่ผู้ติดต่อของคุณอนุญาตเท่านั้น.</target> <note>No comment provided by engineer.</note> </trans-unit> - <trans-unit id="Allow irreversible message deletion only if your contact allows it to you." xml:space="preserve"> - <source>Allow irreversible message deletion only if your contact allows it to you.</source> + <trans-unit id="Allow irreversible message deletion only if your contact allows it to you. (24 hours)" xml:space="preserve"> + <source>Allow irreversible message deletion only if your contact allows it to you. (24 hours)</source> <target>อนุญาตให้ลบข้อความแบบถาวรเฉพาะในกรณีที่ผู้ติดต่อของคุณอนุญาตให้คุณเท่านั้น</target> <note>No comment provided by engineer.</note> </trans-unit> @@ -678,8 +678,8 @@ <target>อนุญาตให้ส่งข้อความที่จะหายไปหลังปิดแชท (disappearing message)</target> <note>No comment provided by engineer.</note> </trans-unit> - <trans-unit id="Allow to irreversibly delete sent messages." xml:space="preserve"> - <source>Allow to irreversibly delete sent messages.</source> + <trans-unit id="Allow to irreversibly delete sent messages. (24 hours)" xml:space="preserve"> + <source>Allow to irreversibly delete sent messages. (24 hours)</source> <target>อนุญาตให้ลบข้อความที่ส่งไปแล้วอย่างถาวร</target> <note>No comment provided by engineer.</note> </trans-unit> @@ -713,8 +713,8 @@ <target>อนุญาตให้ผู้ติดต่อของคุณโทรหาคุณ</target> <note>No comment provided by engineer.</note> </trans-unit> - <trans-unit id="Allow your contacts to irreversibly delete sent messages." xml:space="preserve"> - <source>Allow your contacts to irreversibly delete sent messages.</source> + <trans-unit id="Allow your contacts to irreversibly delete sent messages. (24 hours)" xml:space="preserve"> + <source>Allow your contacts to irreversibly delete sent messages. (24 hours)</source> <target>อนุญาตให้ผู้ติดต่อของคุณลบข้อความที่ส่งแล้วอย่างถาวร</target> <note>No comment provided by engineer.</note> </trans-unit> @@ -887,6 +887,10 @@ <source>Block</source> <note>No comment provided by engineer.</note> </trans-unit> + <trans-unit id="Block for all" xml:space="preserve"> + <source>Block for all</source> + <note>No comment provided by engineer.</note> + </trans-unit> <trans-unit id="Block group members" xml:space="preserve"> <source>Block group members</source> <note>No comment provided by engineer.</note> @@ -895,17 +899,25 @@ <source>Block member</source> <note>No comment provided by engineer.</note> </trans-unit> + <trans-unit id="Block member for all?" xml:space="preserve"> + <source>Block member for all?</source> + <note>No comment provided by engineer.</note> + </trans-unit> <trans-unit id="Block member?" xml:space="preserve"> <source>Block member?</source> <note>No comment provided by engineer.</note> </trans-unit> + <trans-unit id="Blocked by admin" xml:space="preserve"> + <source>Blocked by admin</source> + <note>No comment provided by engineer.</note> + </trans-unit> <trans-unit id="Both you and your contact can add message reactions." xml:space="preserve"> <source>Both you and your contact can add message reactions.</source> <target>ทั้งคุณและผู้ติดต่อของคุณสามารถเพิ่มปฏิกิริยาของข้อความได้</target> <note>No comment provided by engineer.</note> </trans-unit> - <trans-unit id="Both you and your contact can irreversibly delete sent messages." xml:space="preserve"> - <source>Both you and your contact can irreversibly delete sent messages.</source> + <trans-unit id="Both you and your contact can irreversibly delete sent messages. (24 hours)" xml:space="preserve"> + <source>Both you and your contact can irreversibly delete sent messages. (24 hours)</source> <target>ทั้งคุณและผู้ติดต่อของคุณสามารถลบข้อความที่ส่งแล้วอย่างถาวรได้</target> <note>No comment provided by engineer.</note> </trans-unit> @@ -943,9 +955,8 @@ <target>โทร</target> <note>No comment provided by engineer.</note> </trans-unit> - <trans-unit id="Can't delete user profile!" xml:space="preserve"> - <source>Can't delete user profile!</source> - <target>ไม่สามารถลบโปรไฟล์ผู้ใช้ได้!</target> + <trans-unit id="Camera not available" xml:space="preserve"> + <source>Camera not available</source> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="Can't invite contact!" xml:space="preserve"> @@ -1059,6 +1070,10 @@ <target>การแชทหยุดทํางานแล้ว</target> <note>No comment provided by engineer.</note> </trans-unit> + <trans-unit id="Chat is stopped. If you already used this database on another device, you should transfer it back before starting chat." xml:space="preserve"> + <source>Chat is stopped. If you already used this database on another device, you should transfer it back before starting chat.</source> + <note>No comment provided by engineer.</note> + </trans-unit> <trans-unit id="Chat preferences" xml:space="preserve"> <source>Chat preferences</source> <target>ค่ากําหนดในการแชท</target> @@ -1104,6 +1119,10 @@ <target>ลบการสนทนา?</target> <note>No comment provided by engineer.</note> </trans-unit> + <trans-unit id="Clear private notes?" xml:space="preserve"> + <source>Clear private notes?</source> + <note>No comment provided by engineer.</note> + </trans-unit> <trans-unit id="Clear verification" xml:space="preserve"> <source>Clear verification</source> <target>ล้างการยืนยัน</target> @@ -1194,11 +1213,6 @@ This is your own one-time link!</source> <target>เชื่อมต่อผ่านลิงก์</target> <note>No comment provided by engineer.</note> </trans-unit> - <trans-unit id="Connect via link / QR code" xml:space="preserve"> - <source>Connect via link / QR code</source> - <target>เชื่อมต่อผ่านลิงค์ / คิวอาร์โค้ด</target> - <note>No comment provided by engineer.</note> - </trans-unit> <trans-unit id="Connect via one-time link" xml:space="preserve"> <source>Connect via one-time link</source> <note>No comment provided by engineer.</note> @@ -1364,11 +1378,6 @@ This is your own one-time link!</source> <source>Create new profile in [desktop app](https://simplex.chat/downloads/). 💻</source> <note>No comment provided by engineer.</note> </trans-unit> - <trans-unit id="Create one-time invitation link" xml:space="preserve"> - <source>Create one-time invitation link</source> - <target>สร้างลิงก์เชิญแบบใช้ครั้งเดียว</target> - <note>No comment provided by engineer.</note> - </trans-unit> <trans-unit id="Create profile" xml:space="preserve"> <source>Create profile</source> <note>No comment provided by engineer.</note> @@ -1388,11 +1397,23 @@ This is your own one-time link!</source> <target>สร้างโปรไฟล์ของคุณ</target> <note>No comment provided by engineer.</note> </trans-unit> + <trans-unit id="Created at" xml:space="preserve"> + <source>Created at</source> + <note>No comment provided by engineer.</note> + </trans-unit> + <trans-unit id="Created at: %@" xml:space="preserve"> + <source>Created at: %@</source> + <note>copied message info</note> + </trans-unit> <trans-unit id="Created on %@" xml:space="preserve"> <source>Created on %@</source> <target>สร้างเมื่อ %@</target> <note>No comment provided by engineer.</note> </trans-unit> + <trans-unit id="Creating link…" xml:space="preserve"> + <source>Creating link…</source> + <note>No comment provided by engineer.</note> + </trans-unit> <trans-unit id="Current Passcode" xml:space="preserve"> <source>Current Passcode</source> <target>รหัสผ่านปัจจุบัน</target> @@ -1862,6 +1883,10 @@ This cannot be undone!</source> <target>ทำในภายหลัง</target> <note>No comment provided by engineer.</note> </trans-unit> + <trans-unit id="Do not send history to new members." xml:space="preserve"> + <source>Do not send history to new members.</source> + <note>No comment provided by engineer.</note> + </trans-unit> <trans-unit id="Don't create address" xml:space="preserve"> <source>Don't create address</source> <target>อย่าสร้างที่อยู่</target> @@ -1932,6 +1957,10 @@ This cannot be undone!</source> <target>เปิดใช้งานการลบข้อความอัตโนมัติ?</target> <note>No comment provided by engineer.</note> </trans-unit> + <trans-unit id="Enable camera access" xml:space="preserve"> + <source>Enable camera access</source> + <note>No comment provided by engineer.</note> + </trans-unit> <trans-unit id="Enable for all" xml:space="preserve"> <source>Enable for all</source> <target>เปิดใช้งานสําหรับทุกคน</target> @@ -1995,6 +2024,10 @@ This cannot be undone!</source> <target>ข้อความที่ encrypt หรือเหตุการณ์อื่น</target> <note>notification</note> </trans-unit> + <trans-unit id="Encrypted message: app is stopped" xml:space="preserve"> + <source>Encrypted message: app is stopped</source> + <note>notification</note> + </trans-unit> <trans-unit id="Encrypted message: database error" xml:space="preserve"> <source>Encrypted message: database error</source> <target>ข้อความที่ encrypt: ความผิดพลาดในฐานข้อมูล</target> @@ -2134,6 +2167,10 @@ This cannot be undone!</source> <source>Error creating member contact</source> <note>No comment provided by engineer.</note> </trans-unit> + <trans-unit id="Error creating message" xml:space="preserve"> + <source>Error creating message</source> + <note>No comment provided by engineer.</note> + </trans-unit> <trans-unit id="Error creating profile!" xml:space="preserve"> <source>Error creating profile!</source> <target>เกิดข้อผิดพลาดในการสร้างโปรไฟล์!</target> @@ -2218,6 +2255,10 @@ This cannot be undone!</source> <target>โหลดเซิร์ฟเวอร์ %@ ผิดพลาด</target> <note>No comment provided by engineer.</note> </trans-unit> + <trans-unit id="Error opening chat" xml:space="preserve"> + <source>Error opening chat</source> + <note>No comment provided by engineer.</note> + </trans-unit> <trans-unit id="Error receiving file" xml:space="preserve"> <source>Error receiving file</source> <target>เกิดข้อผิดพลาดในการรับไฟล์</target> @@ -2258,6 +2299,10 @@ This cannot be undone!</source> <target>เกิดข้อผิดพลาดในการบันทึกรหัสผ่านผู้ใช้</target> <note>No comment provided by engineer.</note> </trans-unit> + <trans-unit id="Error scanning code: %@" xml:space="preserve"> + <source>Error scanning code: %@</source> + <note>No comment provided by engineer.</note> + </trans-unit> <trans-unit id="Error sending email" xml:space="preserve"> <source>Error sending email</source> <target>เกิดข้อผิดพลาดในการส่งอีเมล</target> @@ -2581,8 +2626,8 @@ This cannot be undone!</source> <target>สมาชิกกลุ่มสามารถเพิ่มการแสดงปฏิกิริยาต่อข้อความได้</target> <note>No comment provided by engineer.</note> </trans-unit> - <trans-unit id="Group members can irreversibly delete sent messages." xml:space="preserve"> - <source>Group members can irreversibly delete sent messages.</source> + <trans-unit id="Group members can irreversibly delete sent messages. (24 hours)" xml:space="preserve"> + <source>Group members can irreversibly delete sent messages. (24 hours)</source> <target>สมาชิกกลุ่มสามารถลบข้อความที่ส่งแล้วอย่างถาวร</target> <note>No comment provided by engineer.</note> </trans-unit> @@ -2691,6 +2736,10 @@ This cannot be undone!</source> <target>ประวัติ</target> <note>No comment provided by engineer.</note> </trans-unit> + <trans-unit id="History is not sent to new members." xml:space="preserve"> + <source>History is not sent to new members.</source> + <note>No comment provided by engineer.</note> + </trans-unit> <trans-unit id="How SimpleX works" xml:space="preserve"> <source>How SimpleX works</source> <target>วิธีการ SimpleX ทํางานอย่างไร</target> @@ -2726,11 +2775,6 @@ This cannot be undone!</source> <target>หากคุณไม่สามารถพบกันในชีวิตจริงได้ ให้แสดงคิวอาร์โค้ดในวิดีโอคอล หรือแชร์ลิงก์</target> <note>No comment provided by engineer.</note> </trans-unit> - <trans-unit id="If you cannot meet in person, you can **scan QR code in the video call**, or your contact can share an invitation link." xml:space="preserve"> - <source>If you cannot meet in person, you can **scan QR code in the video call**, or your contact can share an invitation link.</source> - <target>หากคุณไม่สามารถพบปะด้วยตนเอง คุณสามารถ **สแกนคิวอาร์โค้ดผ่านการสนทนาทางวิดีโอ** หรือผู้ติดต่อของคุณสามารถแชร์ลิงก์เชิญได้</target> - <note>No comment provided by engineer.</note> - </trans-unit> <trans-unit id="If you enter this passcode when opening the app, all app data will be irreversibly removed!" xml:space="preserve"> <source>If you enter this passcode when opening the app, all app data will be irreversibly removed!</source> <target>หากคุณใส่รหัสผ่านนี้เมื่อเปิดแอป ข้อมูลแอปทั้งหมดจะถูกลบอย่างถาวร!</target> @@ -2786,6 +2830,10 @@ This cannot be undone!</source> <target>นำเข้าฐานข้อมูล</target> <note>No comment provided by engineer.</note> </trans-unit> + <trans-unit id="Improved message delivery" xml:space="preserve"> + <source>Improved message delivery</source> + <note>No comment provided by engineer.</note> + </trans-unit> <trans-unit id="Improved privacy and security" xml:space="preserve"> <source>Improved privacy and security</source> <target>ปรับปรุงความเป็นส่วนตัวและความปลอดภัยแล้ว</target> @@ -2885,15 +2933,31 @@ This cannot be undone!</source> <target>อินเตอร์เฟซ</target> <note>No comment provided by engineer.</note> </trans-unit> + <trans-unit id="Invalid QR code" xml:space="preserve"> + <source>Invalid QR code</source> + <note>No comment provided by engineer.</note> + </trans-unit> <trans-unit id="Invalid connection link" xml:space="preserve"> <source>Invalid connection link</source> <target>ลิงค์เชื่อมต่อไม่ถูกต้อง</target> <note>No comment provided by engineer.</note> </trans-unit> + <trans-unit id="Invalid display name!" xml:space="preserve"> + <source>Invalid display name!</source> + <note>No comment provided by engineer.</note> + </trans-unit> + <trans-unit id="Invalid link" xml:space="preserve"> + <source>Invalid link</source> + <note>No comment provided by engineer.</note> + </trans-unit> <trans-unit id="Invalid name!" xml:space="preserve"> <source>Invalid name!</source> <note>No comment provided by engineer.</note> </trans-unit> + <trans-unit id="Invalid response" xml:space="preserve"> + <source>Invalid response</source> + <note>No comment provided by engineer.</note> + </trans-unit> <trans-unit id="Invalid server address!" xml:space="preserve"> <source>Invalid server address!</source> <target>ที่อยู่เซิร์ฟเวอร์ไม่ถูกต้อง!</target> @@ -2984,6 +3048,10 @@ This cannot be undone!</source> <target>เข้าร่วมกลุ่ม</target> <note>No comment provided by engineer.</note> </trans-unit> + <trans-unit id="Join group conversations" xml:space="preserve"> + <source>Join group conversations</source> + <note>No comment provided by engineer.</note> + </trans-unit> <trans-unit id="Join group?" xml:space="preserve"> <source>Join group?</source> <note>No comment provided by engineer.</note> @@ -3007,10 +3075,18 @@ This is your link for group %@!</source> <target>กำลังจะเข้าร่วมกลุ่ม</target> <note>No comment provided by engineer.</note> </trans-unit> + <trans-unit id="Keep" xml:space="preserve"> + <source>Keep</source> + <note>No comment provided by engineer.</note> + </trans-unit> <trans-unit id="Keep the app open to use it from desktop" xml:space="preserve"> <source>Keep the app open to use it from desktop</source> <note>No comment provided by engineer.</note> </trans-unit> + <trans-unit id="Keep unused invitation?" xml:space="preserve"> + <source>Keep unused invitation?</source> + <note>No comment provided by engineer.</note> + </trans-unit> <trans-unit id="Keep your connections" xml:space="preserve"> <source>Keep your connections</source> <target>รักษาการเชื่อมต่อของคุณ</target> @@ -3093,6 +3169,11 @@ This is your link for group %@!</source> <target>ข้อความสด</target> <note>No comment provided by engineer.</note> </trans-unit> + <trans-unit id="Local" xml:space="preserve"> + <source>Local</source> + <target>ในเครื่อง</target> + <note>No comment provided by engineer.</note> + </trans-unit> <trans-unit id="Local name" xml:space="preserve"> <source>Local name</source> <target>ชื่อภายในเครื่องเท่านั้น</target> @@ -3331,6 +3412,10 @@ This is your link for group %@!</source> <target>รหัสผ่านใหม่</target> <note>No comment provided by engineer.</note> </trans-unit> + <trans-unit id="New chat" xml:space="preserve"> + <source>New chat</source> + <note>No comment provided by engineer.</note> + </trans-unit> <trans-unit id="New contact request" xml:space="preserve"> <source>New contact request</source> <target>คำขอติดต่อใหม่</target> @@ -3452,16 +3537,15 @@ This is your link for group %@!</source> - ปิดการใช้งานสมาชิก (บทบาท "ผู้สังเกตการณ์")</target> <note>No comment provided by engineer.</note> </trans-unit> + <trans-unit id="OK" xml:space="preserve"> + <source>OK</source> + <note>No comment provided by engineer.</note> + </trans-unit> <trans-unit id="Off" xml:space="preserve"> <source>Off</source> <target>ปิด</target> <note>No comment provided by engineer.</note> </trans-unit> - <trans-unit id="Off (Local)" xml:space="preserve"> - <source>Off (Local)</source> - <target>ปิด (ในเครื่อง)</target> - <note>No comment provided by engineer.</note> - </trans-unit> <trans-unit id="Ok" xml:space="preserve"> <source>Ok</source> <target>ตกลง</target> @@ -3522,8 +3606,8 @@ This is your link for group %@!</source> <target>มีเพียงคุณเท่านั้นที่สามารถแสดงปฏิกิริยาต่อข้อความได้</target> <note>No comment provided by engineer.</note> </trans-unit> - <trans-unit id="Only you can irreversibly delete messages (your contact can mark them for deletion)." xml:space="preserve"> - <source>Only you can irreversibly delete messages (your contact can mark them for deletion).</source> + <trans-unit id="Only you can irreversibly delete messages (your contact can mark them for deletion). (24 hours)" xml:space="preserve"> + <source>Only you can irreversibly delete messages (your contact can mark them for deletion). (24 hours)</source> <target>มีเพียงคุณเท่านั้นที่สามารถลบข้อความแบบย้อนกลับไม่ได้ (ผู้ติดต่อของคุณสามารถทำเครื่องหมายเพื่อลบได้)</target> <note>No comment provided by engineer.</note> </trans-unit> @@ -3547,8 +3631,8 @@ This is your link for group %@!</source> <target>เฉพาะผู้ติดต่อของคุณเท่านั้นที่สามารถเพิ่มการโต้ตอบข้อความได้</target> <note>No comment provided by engineer.</note> </trans-unit> - <trans-unit id="Only your contact can irreversibly delete messages (you can mark them for deletion)." xml:space="preserve"> - <source>Only your contact can irreversibly delete messages (you can mark them for deletion).</source> + <trans-unit id="Only your contact can irreversibly delete messages (you can mark them for deletion). (24 hours)" xml:space="preserve"> + <source>Only your contact can irreversibly delete messages (you can mark them for deletion). (24 hours)</source> <target>เฉพาะผู้ติดต่อของคุณเท่านั้นที่สามารถลบข้อความแบบย้อนกลับไม่ได้ (คุณสามารถทำเครื่องหมายเพื่อลบได้)</target> <note>No comment provided by engineer.</note> </trans-unit> @@ -3600,9 +3684,16 @@ This is your link for group %@!</source> <target>โปรโตคอลและโค้ดโอเพ่นซอร์ส – ใคร ๆ ก็สามารถเปิดใช้เซิร์ฟเวอร์ได้</target> <note>No comment provided by engineer.</note> </trans-unit> - <trans-unit id="Opening database…" xml:space="preserve"> - <source>Opening database…</source> - <target>กำลังเปิดฐานข้อมูล…</target> + <trans-unit id="Opening app…" xml:space="preserve"> + <source>Opening app…</source> + <note>No comment provided by engineer.</note> + </trans-unit> + <trans-unit id="Or scan QR code" xml:space="preserve"> + <source>Or scan QR code</source> + <note>No comment provided by engineer.</note> + </trans-unit> + <trans-unit id="Or show this code" xml:space="preserve"> + <source>Or show this code</source> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="PING count" xml:space="preserve"> @@ -3645,10 +3736,9 @@ This is your link for group %@!</source> <target>รหัสผ่านที่จะแสดง</target> <note>No comment provided by engineer.</note> </trans-unit> - <trans-unit id="Paste" xml:space="preserve"> - <source>Paste</source> - <target>แปะ</target> - <note>No comment provided by engineer.</note> + <trans-unit id="Past member %@" xml:space="preserve"> + <source>Past member %@</source> + <note>past/unknown group member</note> </trans-unit> <trans-unit id="Paste desktop address" xml:space="preserve"> <source>Paste desktop address</source> @@ -3659,14 +3749,13 @@ This is your link for group %@!</source> <target>แปะภาพ</target> <note>No comment provided by engineer.</note> </trans-unit> - <trans-unit id="Paste received link" xml:space="preserve"> - <source>Paste received link</source> - <target>แปะลิงก์ที่ได้รับ</target> + <trans-unit id="Paste link to connect!" xml:space="preserve"> + <source>Paste link to connect!</source> <note>No comment provided by engineer.</note> </trans-unit> - <trans-unit id="Paste the link you received to connect with your contact." xml:space="preserve"> - <source>Paste the link you received to connect with your contact.</source> - <note>placeholder</note> + <trans-unit id="Paste the link you received" xml:space="preserve"> + <source>Paste the link you received</source> + <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="People can connect to you only via the links you share." xml:space="preserve"> <source>People can connect to you only via the links you share.</source> @@ -3703,6 +3792,11 @@ This is your link for group %@!</source> <target>โปรดตรวจสอบความต้องการของคุณและการตั้งค่าผู้ติดต่อ</target> <note>No comment provided by engineer.</note> </trans-unit> + <trans-unit id="Please contact developers. Error: %@" xml:space="preserve"> + <source>Please contact developers. +Error: %@</source> + <note>No comment provided by engineer.</note> + </trans-unit> <trans-unit id="Please contact group admin." xml:space="preserve"> <source>Please contact group admin.</source> <target>โปรดติดต่อผู้ดูแลกลุ่ม</target> @@ -3788,6 +3882,10 @@ This is your link for group %@!</source> <target>ชื่อไฟล์ส่วนตัว</target> <note>No comment provided by engineer.</note> </trans-unit> + <trans-unit id="Private notes" xml:space="preserve"> + <source>Private notes</source> + <note>name of notes to self</note> + </trans-unit> <trans-unit id="Profile and server connections" xml:space="preserve"> <source>Profile and server connections</source> <target>การเชื่อมต่อโปรไฟล์และเซิร์ฟเวอร์</target> @@ -3906,6 +4004,10 @@ This is your link for group %@!</source> <target>อ่านเพิ่มเติมใน[คู่มือผู้ใช้](https://simplex.chat/docs/guide/app-settings.html#your-simplex-contact-address)</target> <note>No comment provided by engineer.</note> </trans-unit> + <trans-unit id="Read more in [User Guide](https://simplex.chat/docs/guide/chat-profiles.html#incognito-mode)." xml:space="preserve"> + <source>Read more in [User Guide](https://simplex.chat/docs/guide/chat-profiles.html#incognito-mode).</source> + <note>No comment provided by engineer.</note> + </trans-unit> <trans-unit id="Read more in [User Guide](https://simplex.chat/docs/guide/readme.html#connect-to-friends)." xml:space="preserve"> <source>Read more in [User Guide](https://simplex.chat/docs/guide/readme.html#connect-to-friends).</source> <target>อ่านเพิ่มเติมใน[คู่มือผู้ใช้](https://simplex.chat/docs/guide/readme.html#connect-to-friends)</target> @@ -3960,6 +4062,10 @@ This is your link for group %@!</source> <target>กำลังรับผ่าน</target> <note>No comment provided by engineer.</note> </trans-unit> + <trans-unit id="Recent history and improved [directory bot](simplex:/contact#/?v=1-4&smp=smp%3A%2F%2Fu2dS9sG8nMNURyZwqASV4yROM28Er0luVTx5X1CsMrU%3D%40smp4.simplex.im%2FeXSPwqTkKyDO3px4fLf1wx3MvPdjdLW3%23%2F%3Fv%3D1-2%26dh%3DMCowBQYDK2VuAyEAaiv6MkMH44L2TcYrt_CsX3ZvM11WgbMEUn0hkIKTOho%253D%26srv%3Do5vmywmrnaxalvz6wi3zicyftgio6psuvyniis6gco6bp6ekl4cqj4id.onion)." xml:space="preserve"> + <source>Recent history and improved [directory bot](simplex:/contact#/?v=1-4&smp=smp%3A%2F%2Fu2dS9sG8nMNURyZwqASV4yROM28Er0luVTx5X1CsMrU%3D%40smp4.simplex.im%2FeXSPwqTkKyDO3px4fLf1wx3MvPdjdLW3%23%2F%3Fv%3D1-2%26dh%3DMCowBQYDK2VuAyEAaiv6MkMH44L2TcYrt_CsX3ZvM11WgbMEUn0hkIKTOho%253D%26srv%3Do5vmywmrnaxalvz6wi3zicyftgio6psuvyniis6gco6bp6ekl4cqj4id.onion).</source> + <note>No comment provided by engineer.</note> + </trans-unit> <trans-unit id="Recipients see updates as you type them." xml:space="preserve"> <source>Recipients see updates as you type them.</source> <target>ผู้รับจะเห็นการอัปเดตเมื่อคุณพิมพ์</target> @@ -4112,6 +4218,10 @@ This is your link for group %@!</source> <target>กู้คืนข้อผิดพลาดของฐานข้อมูล</target> <note>No comment provided by engineer.</note> </trans-unit> + <trans-unit id="Retry" xml:space="preserve"> + <source>Retry</source> + <note>No comment provided by engineer.</note> + </trans-unit> <trans-unit id="Reveal" xml:space="preserve"> <source>Reveal</source> <target>เปิดเผย</target> @@ -4237,6 +4347,10 @@ This is your link for group %@!</source> <target>เซิร์ฟเวอร์ WebRTC ICE ที่บันทึกไว้จะถูกลบออก</target> <note>No comment provided by engineer.</note> </trans-unit> + <trans-unit id="Saved message" xml:space="preserve"> + <source>Saved message</source> + <note>message info title</note> + </trans-unit> <trans-unit id="Scan QR code" xml:space="preserve"> <source>Scan QR code</source> <target>สแกนคิวอาร์โค้ด</target> @@ -4266,6 +4380,14 @@ This is your link for group %@!</source> <target>ค้นหา</target> <note>No comment provided by engineer.</note> </trans-unit> + <trans-unit id="Search bar accepts invitation links." xml:space="preserve"> + <source>Search bar accepts invitation links.</source> + <note>No comment provided by engineer.</note> + </trans-unit> + <trans-unit id="Search or paste SimpleX link" xml:space="preserve"> + <source>Search or paste SimpleX link</source> + <note>No comment provided by engineer.</note> + </trans-unit> <trans-unit id="Secure queue" xml:space="preserve"> <source>Secure queue</source> <target>คิวที่ปลอดภัย</target> @@ -4370,6 +4492,10 @@ This is your link for group %@!</source> <target>ส่งจากแกลเลอรีหรือแป้นพิมพ์แบบกำหนดเอง</target> <note>No comment provided by engineer.</note> </trans-unit> + <trans-unit id="Send up to 100 last messages to new members." xml:space="preserve"> + <source>Send up to 100 last messages to new members.</source> + <note>No comment provided by engineer.</note> + </trans-unit> <trans-unit id="Sender cancelled file transfer." xml:space="preserve"> <source>Sender cancelled file transfer.</source> <target>ผู้ส่งยกเลิกการโอนไฟล์</target> @@ -4537,9 +4663,8 @@ This is your link for group %@!</source> <target>แชร์ลิงก์</target> <note>No comment provided by engineer.</note> </trans-unit> - <trans-unit id="Share one-time invitation link" xml:space="preserve"> - <source>Share one-time invitation link</source> - <target>แชร์ลิงก์เชิญแบบใช้ครั้งเดียว</target> + <trans-unit id="Share this 1-time invite link" xml:space="preserve"> + <source>Share this 1-time invite link</source> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="Share with contacts" xml:space="preserve"> @@ -4659,16 +4784,15 @@ This is your link for group %@!</source> <target>ใครบางคน</target> <note>notification title</note> </trans-unit> - <trans-unit id="Start a new chat" xml:space="preserve"> - <source>Start a new chat</source> - <target>เริ่มแชทใหม่</target> - <note>No comment provided by engineer.</note> - </trans-unit> <trans-unit id="Start chat" xml:space="preserve"> <source>Start chat</source> <target>เริ่มแชท</target> <note>No comment provided by engineer.</note> </trans-unit> + <trans-unit id="Start chat?" xml:space="preserve"> + <source>Start chat?</source> + <note>No comment provided by engineer.</note> + </trans-unit> <trans-unit id="Start migration" xml:space="preserve"> <source>Start migration</source> <target>เริ่มการย้ายข้อมูล</target> @@ -4793,6 +4917,14 @@ This is your link for group %@!</source> <target>แตะเพื่อเข้าร่วมโหมดไม่ระบุตัวตน</target> <note>No comment provided by engineer.</note> </trans-unit> + <trans-unit id="Tap to paste link" xml:space="preserve"> + <source>Tap to paste link</source> + <note>No comment provided by engineer.</note> + </trans-unit> + <trans-unit id="Tap to scan" xml:space="preserve"> + <source>Tap to scan</source> + <note>No comment provided by engineer.</note> + </trans-unit> <trans-unit id="Tap to start a new chat" xml:space="preserve"> <source>Tap to start a new chat</source> <target>แตะเพื่อเริ่มแชทใหม่</target> @@ -4856,6 +4988,10 @@ It can happen because of some bug or when the connection is compromised.</source <target>ความพยายามในการเปลี่ยนรหัสผ่านของฐานข้อมูลไม่เสร็จสมบูรณ์</target> <note>No comment provided by engineer.</note> </trans-unit> + <trans-unit id="The code you scanned is not a SimpleX link QR code." xml:space="preserve"> + <source>The code you scanned is not a SimpleX link QR code.</source> + <note>No comment provided by engineer.</note> + </trans-unit> <trans-unit id="The connection you accepted will be cancelled!" xml:space="preserve"> <source>The connection you accepted will be cancelled!</source> <target>การเชื่อมต่อที่คุณยอมรับจะถูกยกเลิก!</target> @@ -4921,21 +5057,15 @@ It can happen because of some bug or when the connection is compromised.</source <target>เซิร์ฟเวอร์สำหรับการเชื่อมต่อใหม่ของโปรไฟล์การแชทปัจจุบันของคุณ **%@**</target> <note>No comment provided by engineer.</note> </trans-unit> + <trans-unit id="The text you pasted is not a SimpleX link." xml:space="preserve"> + <source>The text you pasted is not a SimpleX link.</source> + <note>No comment provided by engineer.</note> + </trans-unit> <trans-unit id="Theme" xml:space="preserve"> <source>Theme</source> <target>ธีม</target> <note>No comment provided by engineer.</note> </trans-unit> - <trans-unit id="There should be at least one user profile." xml:space="preserve"> - <source>There should be at least one user profile.</source> - <target>ควรมีโปรไฟล์ผู้ใช้อย่างน้อยหนึ่งโปรไฟล์</target> - <note>No comment provided by engineer.</note> - </trans-unit> - <trans-unit id="There should be at least one visible user profile." xml:space="preserve"> - <source>There should be at least one visible user profile.</source> - <target>ควรมีอย่างน้อยหนึ่งโปรไฟล์ผู้ใช้ที่มองเห็นได้</target> - <note>No comment provided by engineer.</note> - </trans-unit> <trans-unit id="These settings are for your current profile **%@**." xml:space="preserve"> <source>These settings are for your current profile **%@**.</source> <target>การตั้งค่าเหล่านี้ใช้สำหรับโปรไฟล์ปัจจุบันของคุณ **%@**</target> @@ -4964,6 +5094,10 @@ It can happen because of some bug or when the connection is compromised.</source <source>This device name</source> <note>No comment provided by engineer.</note> </trans-unit> + <trans-unit id="This display name is invalid. Please choose another name." xml:space="preserve"> + <source>This display name is invalid. Please choose another name.</source> + <note>No comment provided by engineer.</note> + </trans-unit> <trans-unit id="This group has over %lld members, delivery receipts are not sent." xml:space="preserve"> <source>This group has over %lld members, delivery receipts are not sent.</source> <note>No comment provided by engineer.</note> @@ -5061,16 +5195,15 @@ You will be prompted to complete authentication before this feature is enabled.< <target>พยายามเชื่อมต่อกับเซิร์ฟเวอร์ที่ใช้รับข้อความจากผู้ติดต่อนี้</target> <note>No comment provided by engineer.</note> </trans-unit> + <trans-unit id="Turkish interface" xml:space="preserve"> + <source>Turkish interface</source> + <note>No comment provided by engineer.</note> + </trans-unit> <trans-unit id="Turn off" xml:space="preserve"> <source>Turn off</source> <target>ปิด</target> <note>No comment provided by engineer.</note> </trans-unit> - <trans-unit id="Turn off notifications?" xml:space="preserve"> - <source>Turn off notifications?</source> - <target>ปิดการแจ้งเตือนไหม?</target> - <note>No comment provided by engineer.</note> - </trans-unit> <trans-unit id="Turn on" xml:space="preserve"> <source>Turn on</source> <target>เปิด</target> @@ -5085,10 +5218,18 @@ You will be prompted to complete authentication before this feature is enabled.< <source>Unblock</source> <note>No comment provided by engineer.</note> </trans-unit> + <trans-unit id="Unblock for all" xml:space="preserve"> + <source>Unblock for all</source> + <note>No comment provided by engineer.</note> + </trans-unit> <trans-unit id="Unblock member" xml:space="preserve"> <source>Unblock member</source> <note>No comment provided by engineer.</note> </trans-unit> + <trans-unit id="Unblock member for all?" xml:space="preserve"> + <source>Unblock member for all?</source> + <note>No comment provided by engineer.</note> + </trans-unit> <trans-unit id="Unblock member?" xml:space="preserve"> <source>Unblock member?</source> <note>No comment provided by engineer.</note> @@ -5183,6 +5324,10 @@ To connect, please ask your contact to create another connection link and check <target>เปลี่ยนเป็นยังไม่ได้อ่าน</target> <note>No comment provided by engineer.</note> </trans-unit> + <trans-unit id="Up to 100 last messages are sent to new members." xml:space="preserve"> + <source>Up to 100 last messages are sent to new members.</source> + <note>No comment provided by engineer.</note> + </trans-unit> <trans-unit id="Update" xml:space="preserve"> <source>Update</source> <target>อัปเดต</target> @@ -5265,6 +5410,10 @@ To connect, please ask your contact to create another connection link and check <source>Use new incognito profile</source> <note>No comment provided by engineer.</note> </trans-unit> + <trans-unit id="Use only local notifications?" xml:space="preserve"> + <source>Use only local notifications?</source> + <note>No comment provided by engineer.</note> + </trans-unit> <trans-unit id="Use server" xml:space="preserve"> <source>Use server</source> <target>ใช้เซิร์ฟเวอร์</target> @@ -5341,6 +5490,10 @@ To connect, please ask your contact to create another connection link and check <target>ดูรหัสความปลอดภัย</target> <note>No comment provided by engineer.</note> </trans-unit> + <trans-unit id="Visible history" xml:space="preserve"> + <source>Visible history</source> + <note>chat feature</note> + </trans-unit> <trans-unit id="Voice messages" xml:space="preserve"> <source>Voice messages</source> <target>ข้อความเสียง</target> @@ -5425,11 +5578,19 @@ To connect, please ask your contact to create another connection link and check <target>เมื่อคุณแชร์โปรไฟล์ที่ไม่ระบุตัวตนกับใครสักคน โปรไฟล์นี้จะใช้สำหรับกลุ่มที่พวกเขาเชิญคุณ</target> <note>No comment provided by engineer.</note> </trans-unit> + <trans-unit id="With encrypted files and media." xml:space="preserve"> + <source>With encrypted files and media.</source> + <note>No comment provided by engineer.</note> + </trans-unit> <trans-unit id="With optional welcome message." xml:space="preserve"> <source>With optional welcome message.</source> <target>พร้อมข้อความต้อนรับที่ไม่บังคับ</target> <note>No comment provided by engineer.</note> </trans-unit> + <trans-unit id="With reduced battery usage." xml:space="preserve"> + <source>With reduced battery usage.</source> + <note>No comment provided by engineer.</note> + </trans-unit> <trans-unit id="Wrong database passphrase" xml:space="preserve"> <source>Wrong database passphrase</source> <target>รหัสผ่านฐานข้อมูลไม่ถูกต้อง</target> @@ -5514,11 +5675,6 @@ Repeat join request?</source> <target>คุณสามารถรับสายจากหน้าจอล็อกโดยไม่ต้องมีการตรวจสอบสิทธิ์อุปกรณ์และแอป</target> <note>No comment provided by engineer.</note> </trans-unit> - <trans-unit id="You can also connect by clicking the link. If it opens in the browser, click **Open in mobile app** button." xml:space="preserve"> - <source>You can also connect by clicking the link. If it opens in the browser, click **Open in mobile app** button.</source> - <target>คุณสามารถเชื่อมต่อได้โดยคลิกที่ลิงค์ หากเปิดในเบราว์เซอร์ ให้คลิกปุ่ม **เปิดในแอปมือถือ**</target> - <note>No comment provided by engineer.</note> - </trans-unit> <trans-unit id="You can create it later" xml:space="preserve"> <source>You can create it later</source> <target>คุณสามารถสร้างได้ในภายหลัง</target> @@ -5539,6 +5695,10 @@ Repeat join request?</source> <target>คุณสามารถซ่อนหรือปิดเสียงโปรไฟล์ผู้ใช้ - ปัดไปทางขวา</target> <note>No comment provided by engineer.</note> </trans-unit> + <trans-unit id="You can make it visible to your SimpleX contacts via Settings." xml:space="preserve"> + <source>You can make it visible to your SimpleX contacts via Settings.</source> + <note>No comment provided by engineer.</note> + </trans-unit> <trans-unit id="You can now send messages to %@" xml:space="preserve"> <source>You can now send messages to %@</source> <target>ตอนนี้คุณสามารถส่งข้อความถึง %@</target> @@ -5579,6 +5739,10 @@ Repeat join request?</source> <target>คุณสามารถใช้มาร์กดาวน์เพื่อจัดรูปแบบข้อความ:</target> <note>No comment provided by engineer.</note> </trans-unit> + <trans-unit id="You can view invitation link again in connection details." xml:space="preserve"> + <source>You can view invitation link again in connection details.</source> + <note>No comment provided by engineer.</note> + </trans-unit> <trans-unit id="You can't send messages!" xml:space="preserve"> <source>You can't send messages!</source> <target>คุณไม่สามารถส่งข้อความได้!</target> @@ -5762,13 +5926,6 @@ You can cancel this connection and remove the contact (and try later with a new <target>ผู้ติดต่อของคุณสามารถอนุญาตให้ลบข้อความทั้งหมดได้</target> <note>No comment provided by engineer.</note> </trans-unit> - <trans-unit id="Your contacts in SimpleX will see it. You can change it in Settings." xml:space="preserve"> - <source>Your contacts in SimpleX will see it. -You can change it in Settings.</source> - <target>ผู้ติดต่อของคุณใน SimpleX จะเห็น -คุณสามารถเปลี่ยนได้ในการตั้งค่า</target> - <note>No comment provided by engineer.</note> - </trans-unit> <trans-unit id="Your contacts will remain connected." xml:space="preserve"> <source>Your contacts will remain connected.</source> <target>ผู้ติดต่อของคุณจะยังคงเชื่อมต่ออยู่</target> @@ -5916,6 +6073,14 @@ SimpleX servers cannot see your profile.</source> <source>blocked</source> <note>No comment provided by engineer.</note> </trans-unit> + <trans-unit id="blocked %@" xml:space="preserve"> + <source>blocked %@</source> + <note>rcv group event chat item</note> + </trans-unit> + <trans-unit id="blocked by admin" xml:space="preserve"> + <source>blocked by admin</source> + <note>blocked chat item</note> + </trans-unit> <trans-unit id="bold" xml:space="preserve"> <source>bold</source> <target>ตัวหนา</target> @@ -6035,6 +6200,10 @@ SimpleX servers cannot see your profile.</source> <target>การเชื่อมต่อ:%@</target> <note>connection information</note> </trans-unit> + <trans-unit id="contact %@ changed to %@" xml:space="preserve"> + <source>contact %1$@ changed to %2$@</source> + <note>profile update event chat item</note> + </trans-unit> <trans-unit id="contact has e2e encryption" xml:space="preserve"> <source>contact has e2e encryption</source> <target>ผู้ติดต่อมีการ encrypt จากต้นจนจบ</target> @@ -6302,6 +6471,10 @@ SimpleX servers cannot see your profile.</source> <target>สมาชิก</target> <note>member role</note> </trans-unit> + <trans-unit id="member %@ changed to %@" xml:space="preserve"> + <source>member %1$@ changed to %2$@</source> + <note>profile update event chat item</note> + </trans-unit> <trans-unit id="member connected" xml:space="preserve"> <source>connected</source> <target>เชื่อมต่อสำเร็จ</target> @@ -6424,6 +6597,14 @@ SimpleX servers cannot see your profile.</source> <target>ถูกลบแล้ว %@</target> <note>rcv group event chat item</note> </trans-unit> + <trans-unit id="removed contact address" xml:space="preserve"> + <source>removed contact address</source> + <note>profile update event chat item</note> + </trans-unit> + <trans-unit id="removed profile picture" xml:space="preserve"> + <source>removed profile picture</source> + <note>profile update event chat item</note> + </trans-unit> <trans-unit id="removed you" xml:space="preserve"> <source>removed you</source> <target>ลบคุณออกแล้ว</target> @@ -6453,6 +6634,14 @@ SimpleX servers cannot see your profile.</source> <source>send direct message</source> <note>No comment provided by engineer.</note> </trans-unit> + <trans-unit id="set new contact address" xml:space="preserve"> + <source>set new contact address</source> + <note>profile update event chat item</note> + </trans-unit> + <trans-unit id="set new profile picture" xml:space="preserve"> + <source>set new profile picture</source> + <note>profile update event chat item</note> + </trans-unit> <trans-unit id="starting…" xml:space="preserve"> <source>starting…</source> <target>กำลังเริ่มต้น…</target> @@ -6468,16 +6657,28 @@ SimpleX servers cannot see your profile.</source> <target>ผู้ติดต่อนี้</target> <note>notification title</note> </trans-unit> + <trans-unit id="unblocked %@" xml:space="preserve"> + <source>unblocked %@</source> + <note>rcv group event chat item</note> + </trans-unit> <trans-unit id="unknown" xml:space="preserve"> <source>unknown</source> <target>ไม่ทราบ</target> <note>connection info</note> </trans-unit> + <trans-unit id="unknown status" xml:space="preserve"> + <source>unknown status</source> + <note>No comment provided by engineer.</note> + </trans-unit> <trans-unit id="updated group profile" xml:space="preserve"> <source>updated group profile</source> <target>อัปเดตโปรไฟล์กลุ่มแล้ว</target> <note>rcv group event chat item</note> </trans-unit> + <trans-unit id="updated profile" xml:space="preserve"> + <source>updated profile</source> + <note>profile update event chat item</note> + </trans-unit> <trans-unit id="v%@" xml:space="preserve"> <source>v%@</source> <note>No comment provided by engineer.</note> @@ -6547,6 +6748,10 @@ SimpleX servers cannot see your profile.</source> <target>คุณเป็นผู้สังเกตการณ์</target> <note>No comment provided by engineer.</note> </trans-unit> + <trans-unit id="you blocked %@" xml:space="preserve"> + <source>you blocked %@</source> + <note>snd group event chat item</note> + </trans-unit> <trans-unit id="you changed address" xml:space="preserve"> <source>you changed address</source> <target>คุณเปลี่ยนที่อยู่แล้ว</target> @@ -6587,6 +6792,10 @@ SimpleX servers cannot see your profile.</source> <target>คุณแชร์ลิงก์แบบใช้ครั้งเดียวโดยไม่ระบุตัวตนแล้ว</target> <note>chat list item description</note> </trans-unit> + <trans-unit id="you unblocked %@" xml:space="preserve"> + <source>you unblocked %@</source> + <note>snd group event chat item</note> + </trans-unit> <trans-unit id="you: " xml:space="preserve"> <source>you: </source> <target>คุณ: </target> diff --git a/apps/ios/SimpleX Localizations/tr.xcloc/Localized Contents/Shared/Assets.xcassets/AccentColor.colorset/Contents.json b/apps/ios/SimpleX Localizations/tr.xcloc/Localized Contents/Shared/Assets.xcassets/AccentColor.colorset/Contents.json new file mode 100644 index 0000000000..e44aedf64a --- /dev/null +++ b/apps/ios/SimpleX Localizations/tr.xcloc/Localized Contents/Shared/Assets.xcassets/AccentColor.colorset/Contents.json @@ -0,0 +1,15 @@ +{ + "colors" : [ + { + "idiom" : "universal", + "locale" : "tr" + } + ], + "properties" : { + "localizable" : true + }, + "info" : { + "version" : 1, + "author" : "xcode" + } +} \ No newline at end of file diff --git a/apps/ios/SimpleX Localizations/tr.xcloc/Localized Contents/Shared/Assets.xcassets/Contents.json b/apps/ios/SimpleX Localizations/tr.xcloc/Localized Contents/Shared/Assets.xcassets/Contents.json new file mode 100644 index 0000000000..73c00596a7 --- /dev/null +++ b/apps/ios/SimpleX Localizations/tr.xcloc/Localized Contents/Shared/Assets.xcassets/Contents.json @@ -0,0 +1,6 @@ +{ + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/apps/ios/SimpleX Localizations/tr.xcloc/Localized Contents/tr.xliff b/apps/ios/SimpleX Localizations/tr.xcloc/Localized Contents/tr.xliff index 4b2ad1548a..09bc39f141 100644 --- a/apps/ios/SimpleX Localizations/tr.xcloc/Localized Contents/tr.xliff +++ b/apps/ios/SimpleX Localizations/tr.xcloc/Localized Contents/tr.xliff @@ -2,2166 +2,3109 @@ <xliff xmlns="urn:oasis:names:tc:xliff:document:1.2" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" version="1.2" xsi:schemaLocation="urn:oasis:names:tc:xliff:document:1.2 http://docs.oasis-open.org/xliff/v1.2/os/xliff-core-1.2-strict.xsd"> <file original="en.lproj/Localizable.strings" source-language="en" target-language="tr" datatype="plaintext"> <header> - <tool tool-id="com.apple.dt.xcode" tool-name="Xcode" tool-version="14.3.1" build-num="14E300c"/> + <tool tool-id="com.apple.dt.xcode" tool-name="Xcode" tool-version="15.0" build-num="15A240d"/> </header> <body> <trans-unit id=" " xml:space="preserve"> <source> </source> + <target> +</target> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id=" " xml:space="preserve"> <source> </source> + <target> </target> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id=" " xml:space="preserve"> <source> </source> + <target> </target> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id=" " xml:space="preserve"> <source> </source> + <target> </target> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id=" (" xml:space="preserve"> <source> (</source> + <target> (</target> <note>No comment provided by engineer.</note> </trans-unit> - <trans-unit id=" (can be copied)" xml:space="preserve" approved="no"> + <trans-unit id=" (can be copied)" xml:space="preserve"> <source> (can be copied)</source> - <target state="translated"> (kopyalanabilir)</target> + <target> (kopyalanabilir)</target> <note>No comment provided by engineer.</note> </trans-unit> - <trans-unit id="!1 colored!" xml:space="preserve" approved="no"> + <trans-unit id="!1 colored!" xml:space="preserve"> <source>!1 colored!</source> - <target state="translated">!1 renkli!</target> + <target>!1 renklendirilmiş!</target> <note>No comment provided by engineer.</note> </trans-unit> - <trans-unit id="#secret#" xml:space="preserve" approved="no"> - <source>#secret#</source> - <target state="translated">#gizli#</target> - <note>No comment provided by engineer.</note> + <trans-unit id="# %@" xml:space="preserve"> + <source># %@</source> + <target># %@</target> + <note>copied message info title, # <title></note> </trans-unit> - <trans-unit id="%@" xml:space="preserve" approved="no"> - <source>%@</source> - <target state="translated">%@</target> - <note>No comment provided by engineer.</note> - </trans-unit> - <trans-unit id="%@ %@" xml:space="preserve" approved="no"> - <source>%@ %@</source> - <target state="translated">%@ %@</target> - <note>No comment provided by engineer.</note> - </trans-unit> - <trans-unit id="%@ (current)" xml:space="preserve" approved="no"> - <source>%@ (current)</source> - <target state="translated">%@ (güncel)</target> - <note>No comment provided by engineer.</note> - </trans-unit> - <trans-unit id="%@ (current):" xml:space="preserve" approved="no"> - <source>%@ (current):</source> - <target state="translated">%@ (güncel):</target> + <trans-unit id="## History" xml:space="preserve"> + <source>## History</source> + <target>## Geçmiş</target> <note>copied message info</note> </trans-unit> - <trans-unit id="%@ / %@" xml:space="preserve" approved="no"> + <trans-unit id="## In reply to" xml:space="preserve"> + <source>## In reply to</source> + <target>## cevap olarak</target> + <note>copied message info</note> + </trans-unit> + <trans-unit id="#secret#" xml:space="preserve"> + <source>#secret#</source> + <target>#gizli#</target> + <note>No comment provided by engineer.</note> + </trans-unit> + <trans-unit id="%@" xml:space="preserve"> + <source>%@</source> + <target>%@</target> + <note>No comment provided by engineer.</note> + </trans-unit> + <trans-unit id="%@ %@" xml:space="preserve"> + <source>%@ %@</source> + <target>%@ %@</target> + <note>No comment provided by engineer.</note> + </trans-unit> + <trans-unit id="%@ (current)" xml:space="preserve"> + <source>%@ (current)</source> + <target>%@ (güncel)</target> + <note>No comment provided by engineer.</note> + </trans-unit> + <trans-unit id="%@ (current):" xml:space="preserve"> + <source>%@ (current):</source> + <target>%@ (güncel):</target> + <note>copied message info</note> + </trans-unit> + <trans-unit id="%@ / %@" xml:space="preserve"> <source>%@ / %@</source> - <target state="translated">%@ / %@</target> + <target>%@ / %@</target> + <note>No comment provided by engineer.</note> + </trans-unit> + <trans-unit id="%@ and %@" xml:space="preserve"> + <source>%@ and %@</source> + <target>%@ ve %@</target> + <note>No comment provided by engineer.</note> + </trans-unit> + <trans-unit id="%@ and %@ connected" xml:space="preserve"> + <source>%@ and %@ connected</source> + <target>%@ ve %@ bağlandı</target> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="%@ at %@:" xml:space="preserve"> <source>%1$@ at %2$@:</source> + <target>%1$@, %2$@ de</target> <note>copied message info, <sender> at <time></note> </trans-unit> - <trans-unit id="%@ is connected!" xml:space="preserve" approved="no"> + <trans-unit id="%@ connected" xml:space="preserve"> + <source>%@ connected</source> + <target>%@ bağlandı</target> + <note>No comment provided by engineer.</note> + </trans-unit> + <trans-unit id="%@ is connected!" xml:space="preserve"> <source>%@ is connected!</source> - <target state="translated">%@ bağlandı!</target> + <target>%@ bağlandı!</target> <note>notification title</note> </trans-unit> - <trans-unit id="%@ is not verified" xml:space="preserve" approved="no"> + <trans-unit id="%@ is not verified" xml:space="preserve"> <source>%@ is not verified</source> - <target state="translated">%@ onaylanmadı</target> + <target>%@ onaylanmadı</target> <note>No comment provided by engineer.</note> </trans-unit> - <trans-unit id="%@ is verified" xml:space="preserve" approved="no"> + <trans-unit id="%@ is verified" xml:space="preserve"> <source>%@ is verified</source> - <target state="translated">%@ onaylandı</target> + <target>%@ onaylandı</target> <note>No comment provided by engineer.</note> </trans-unit> - <trans-unit id="%@ servers" xml:space="preserve" approved="no"> + <trans-unit id="%@ servers" xml:space="preserve"> <source>%@ servers</source> - <target state="translated">%@ sunucuları</target> + <target>%@ sunucuları</target> <note>No comment provided by engineer.</note> </trans-unit> - <trans-unit id="%@ wants to connect!" xml:space="preserve" approved="no"> + <trans-unit id="%@ wants to connect!" xml:space="preserve"> <source>%@ wants to connect!</source> - <target state="translated">%@ bağlanmak istiyor!</target> + <target>%@ bağlanmak istiyor!</target> <note>notification title</note> </trans-unit> - <trans-unit id="%@:" xml:space="preserve" approved="no"> + <trans-unit id="%@, %@ and %lld members" xml:space="preserve"> + <source>%@, %@ and %lld members</source> + <target>%@, %@ ve %lld üyeleri</target> + <note>No comment provided by engineer.</note> + </trans-unit> + <trans-unit id="%@, %@ and %lld other members connected" xml:space="preserve"> + <source>%@, %@ and %lld other members connected</source> + <target>%@, %@ ve %lld diğer üyeler bağlandı</target> + <note>No comment provided by engineer.</note> + </trans-unit> + <trans-unit id="%@:" xml:space="preserve"> <source>%@:</source> - <target state="translated">%@:</target> + <target>%@:</target> <note>copied message info</note> </trans-unit> - <trans-unit id="%d days" xml:space="preserve" approved="no"> + <trans-unit id="%d days" xml:space="preserve"> <source>%d days</source> - <target state="translated">%d gün</target> + <target>%d gün</target> <note>time interval</note> </trans-unit> - <trans-unit id="%d hours" xml:space="preserve" approved="no"> + <trans-unit id="%d hours" xml:space="preserve"> <source>%d hours</source> - <target state="translated">%d saat</target> + <target>%d saat</target> <note>time interval</note> </trans-unit> - <trans-unit id="%d min" xml:space="preserve" approved="no"> + <trans-unit id="%d min" xml:space="preserve"> <source>%d min</source> - <target state="translated">%d dakika</target> + <target>%d dakika</target> <note>time interval</note> </trans-unit> - <trans-unit id="%d months" xml:space="preserve" approved="no"> + <trans-unit id="%d months" xml:space="preserve"> <source>%d months</source> - <target state="translated">%d ay</target> + <target>%d ay</target> <note>time interval</note> </trans-unit> - <trans-unit id="%d sec" xml:space="preserve" approved="no"> + <trans-unit id="%d sec" xml:space="preserve"> <source>%d sec</source> - <target state="translated">%d saniye</target> + <target>%d saniye</target> <note>time interval</note> </trans-unit> - <trans-unit id="%d skipped message(s)" xml:space="preserve" approved="no"> + <trans-unit id="%d skipped message(s)" xml:space="preserve"> <source>%d skipped message(s)</source> - <target state="translated">%d okunmamış mesaj(lar)</target> + <target>%d okunmamış mesaj(lar)</target> <note>integrity error chat item</note> </trans-unit> - <trans-unit id="%d weeks" xml:space="preserve" approved="no"> + <trans-unit id="%d weeks" xml:space="preserve"> <source>%d weeks</source> - <target state="translated">%d hafta</target> + <target>%d hafta</target> <note>time interval</note> </trans-unit> - <trans-unit id="%lld" xml:space="preserve" approved="no"> + <trans-unit id="%lld" xml:space="preserve"> <source>%lld</source> - <target state="translated">%lld</target> + <target>%lld</target> <note>No comment provided by engineer.</note> </trans-unit> - <trans-unit id="%lld %@" xml:space="preserve" approved="no"> + <trans-unit id="%lld %@" xml:space="preserve"> <source>%lld %@</source> - <target state="translated">%lld %@</target> + <target>%lld %@</target> <note>No comment provided by engineer.</note> </trans-unit> - <trans-unit id="%lld contact(s) selected" xml:space="preserve" approved="no"> + <trans-unit id="%lld contact(s) selected" xml:space="preserve"> <source>%lld contact(s) selected</source> - <target state="translated">%lld kişi seçildi</target> + <target>%lld kişi seçildi</target> <note>No comment provided by engineer.</note> </trans-unit> - <trans-unit id="%lld file(s) with total size of %@" xml:space="preserve" approved="no"> + <trans-unit id="%lld file(s) with total size of %@" xml:space="preserve"> <source>%lld file(s) with total size of %@</source> - <target state="translated">%lld dosya , toplam büyüklüğü %@</target> + <target>%lld dosya , toplam büyüklüğü %@</target> <note>No comment provided by engineer.</note> </trans-unit> - <trans-unit id="%lld members" xml:space="preserve" approved="no"> + <trans-unit id="%lld group events" xml:space="preserve"> + <source>%lld group events</source> + <target>%lld grup etkinlikleri</target> + <note>No comment provided by engineer.</note> + </trans-unit> + <trans-unit id="%lld members" xml:space="preserve"> <source>%lld members</source> - <target state="translated">%lld üyeler</target> + <target>%lld üyeler</target> <note>No comment provided by engineer.</note> </trans-unit> - <trans-unit id="%lld minutes" xml:space="preserve" approved="no"> + <trans-unit id="%lld messages blocked" xml:space="preserve"> + <source>%lld messages blocked</source> + <target>%lld mesajlar engellendi</target> + <note>No comment provided by engineer.</note> + </trans-unit> + <trans-unit id="%lld messages blocked by admin" xml:space="preserve"> + <source>%lld messages blocked by admin</source> + <note>No comment provided by engineer.</note> + </trans-unit> + <trans-unit id="%lld messages marked deleted" xml:space="preserve"> + <source>%lld messages marked deleted</source> + <target>%lld mesajlar silinmiş olarak işaretlendi</target> + <note>No comment provided by engineer.</note> + </trans-unit> + <trans-unit id="%lld messages moderated by %@" xml:space="preserve"> + <source>%lld messages moderated by %@</source> + <target>%lld mesajları %@ tarafından yönetildi</target> + <note>No comment provided by engineer.</note> + </trans-unit> + <trans-unit id="%lld minutes" xml:space="preserve"> <source>%lld minutes</source> - <target state="translated">%lld dakika</target> + <target>%lld dakika</target> <note>No comment provided by engineer.</note> </trans-unit> - <trans-unit id="%lld second(s)" xml:space="preserve" approved="no"> + <trans-unit id="%lld new interface languages" xml:space="preserve"> + <source>%lld new interface languages</source> + <target>%lld yeni arayüz dilleri</target> + <note>No comment provided by engineer.</note> + </trans-unit> + <trans-unit id="%lld second(s)" xml:space="preserve"> <source>%lld second(s)</source> - <target state="translated">%lld saniye</target> + <target>%lld saniye</target> <note>No comment provided by engineer.</note> </trans-unit> - <trans-unit id="%lld seconds" xml:space="preserve" approved="no"> + <trans-unit id="%lld seconds" xml:space="preserve"> <source>%lld seconds</source> - <target state="translated">%lld saniye</target> + <target>%lld saniye</target> <note>No comment provided by engineer.</note> </trans-unit> - <trans-unit id="%lldd" xml:space="preserve" approved="no"> + <trans-unit id="%lldd" xml:space="preserve"> <source>%lldd</source> - <target state="translated">%lldd</target> + <target>%lldd</target> <note>No comment provided by engineer.</note> </trans-unit> - <trans-unit id="%lldh" xml:space="preserve" approved="no"> + <trans-unit id="%lldh" xml:space="preserve"> <source>%lldh</source> - <target state="translated">%lldh</target> + <target>%lldh</target> <note>No comment provided by engineer.</note> </trans-unit> - <trans-unit id="%lldk" xml:space="preserve" approved="no"> + <trans-unit id="%lldk" xml:space="preserve"> <source>%lldk</source> - <target state="translated">%lldk</target> + <target>%lldk</target> <note>No comment provided by engineer.</note> </trans-unit> - <trans-unit id="%lldm" xml:space="preserve" approved="no"> + <trans-unit id="%lldm" xml:space="preserve"> <source>%lldm</source> - <target state="translated">%lldm</target> + <target>%lldm</target> <note>No comment provided by engineer.</note> </trans-unit> - <trans-unit id="%lldmth" xml:space="preserve" approved="no"> + <trans-unit id="%lldmth" xml:space="preserve"> <source>%lldmth</source> - <target state="translated">%lldmth</target> + <target>%lldmth</target> <note>No comment provided by engineer.</note> </trans-unit> - <trans-unit id="%llds" xml:space="preserve" approved="no"> + <trans-unit id="%llds" xml:space="preserve"> <source>%llds</source> - <target state="translated">%llds</target> + <target>%llds</target> <note>No comment provided by engineer.</note> </trans-unit> - <trans-unit id="%lldw" xml:space="preserve" approved="no"> + <trans-unit id="%lldw" xml:space="preserve"> <source>%lldw</source> - <target state="translated">%lldw</target> + <target>%lldw</target> <note>No comment provided by engineer.</note> </trans-unit> - <trans-unit id="%u messages failed to decrypt." xml:space="preserve" approved="no"> + <trans-unit id="%u messages failed to decrypt." xml:space="preserve"> <source>%u messages failed to decrypt.</source> - <target state="translated">%u mesaj deşifrelenememektedir.</target> + <target>%u mesajın şifreleme çözümü başarısız oldu.</target> <note>No comment provided by engineer.</note> </trans-unit> - <trans-unit id="%u messages skipped." xml:space="preserve" approved="no"> + <trans-unit id="%u messages skipped." xml:space="preserve"> <source>%u messages skipped.</source> - <target state="translated">%u mesaj atlandı</target> + <target>%u mesaj atlandı</target> <note>No comment provided by engineer.</note> </trans-unit> - <trans-unit id="(" xml:space="preserve" approved="no"> + <trans-unit id="(" xml:space="preserve"> <source>(</source> - <target state="translated">(</target> + <target>(</target> <note>No comment provided by engineer.</note> </trans-unit> - <trans-unit id=")" xml:space="preserve" approved="no"> + <trans-unit id="(new)" xml:space="preserve"> + <source>(new)</source> + <target>(yeni)</target> + <note>No comment provided by engineer.</note> + </trans-unit> + <trans-unit id="(this device v%@)" xml:space="preserve"> + <source>(this device v%@)</source> + <target>(bu cihaz v%@)</target> + <note>No comment provided by engineer.</note> + </trans-unit> + <trans-unit id=")" xml:space="preserve"> <source>)</source> - <target state="translated">)</target> + <target>)</target> <note>No comment provided by engineer.</note> </trans-unit> - <trans-unit id="**Add new contact**: to create your one-time QR Code for your contact." xml:space="preserve" approved="no"> + <trans-unit id="**Add contact**: to create a new invitation link, or connect via a link you received." xml:space="preserve"> + <source>**Add contact**: to create a new invitation link, or connect via a link you received.</source> + <target>**Kişi ekle**: yeni bir davet bağlantısı oluşturmak için, ya da aldığın bağlantıyla bağlan.</target> + <note>No comment provided by engineer.</note> + </trans-unit> + <trans-unit id="**Add new contact**: to create your one-time QR Code for your contact." xml:space="preserve"> <source>**Add new contact**: to create your one-time QR Code or link for your contact.</source> - <target state="translated">**Yeni kişi ekleyin**: tek seferlik QR Kodunuzu oluşturmak veya kişisel ulaşım bilgileri bağlantısı için.</target> + <target>**Yeni kişi ekleyin**: tek seferlik QR Kodunuzu oluşturmak veya kişisel ulaşım bilgileri bağlantısı için.</target> <note>No comment provided by engineer.</note> </trans-unit> - <trans-unit id="**Create link / QR code** for your contact to use." xml:space="preserve" approved="no"> - <source>**Create link / QR code** for your contact to use.</source> - <target state="translated">Kişisel kullanım için **Bağlantı / QR Kodu**.</target> + <trans-unit id="**Create group**: to create a new group." xml:space="preserve"> + <source>**Create group**: to create a new group.</source> + <target>**Grup oluştur**: yeni bir grup oluşturmak için.</target> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="**More private**: check new messages every 20 minutes. Device token is shared with SimpleX Chat server, but not how many contacts or messages you have." xml:space="preserve"> <source>**More private**: check new messages every 20 minutes. Device token is shared with SimpleX Chat server, but not how many contacts or messages you have.</source> + <target>**Daha gizli**: her 20 dakikada yeni mesajlar için kontrol et. Cihaz jetonu SimpleX Chat sunucusuyla paylaşılacak, ama ne kadar kişi veya mesaja sahip olduğun paylaşılmayacak.</target> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="**Most private**: do not use SimpleX Chat notifications server, check messages periodically in the background (depends on how often you use the app)." xml:space="preserve"> <source>**Most private**: do not use SimpleX Chat notifications server, check messages periodically in the background (depends on how often you use the app).</source> - <note>No comment provided by engineer.</note> - </trans-unit> - <trans-unit id="**Paste received link** or open it in the browser and tap **Open in mobile app**." xml:space="preserve"> - <source>**Paste received link** or open it in the browser and tap **Open in mobile app**.</source> + <target>**En gizli**: SimpleX Chat bildirim sunucusunu kullanma, arkaplanda mesajları periyodik olarak kontrol edin (uygulamayı ne sıklıkta kullandığınıza bağlıdır).</target> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="**Please note**: you will NOT be able to recover or change passphrase if you lose it." xml:space="preserve"> <source>**Please note**: you will NOT be able to recover or change passphrase if you lose it.</source> + <target>**Lütfen aklınızda bulunsun**: eğer parolanızı kaybederseniz parolanızı değiştirme veya geri kurtarma ihtimaliniz YOKTUR.</target> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="**Recommended**: device token and notifications are sent to SimpleX Chat notification server, but not the message content, size or who it is from." xml:space="preserve"> <source>**Recommended**: device token and notifications are sent to SimpleX Chat notification server, but not the message content, size or who it is from.</source> - <note>No comment provided by engineer.</note> - </trans-unit> - <trans-unit id="**Scan QR code**: to connect to your contact in person or via video call." xml:space="preserve"> - <source>**Scan QR code**: to connect to your contact in person or via video call.</source> + <target>**Önerilen**: cihaz tokeni ve bildirimler SimpleX Chat bildirim sunucularına gönderilir, ama mesajın içeriği, boyutu veya kimden geldiği gönderilmez.</target> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="**Warning**: Instant push notifications require passphrase saved in Keychain." xml:space="preserve"> <source>**Warning**: Instant push notifications require passphrase saved in Keychain.</source> + <target>**Dikkat**: Anında iletilen bildirimlere Anahtar Zinciri'nde kaydedilmiş parola gereklidir.</target> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="**e2e encrypted** audio call" xml:space="preserve"> <source>**e2e encrypted** audio call</source> + <target>**uçtan uca şifrelenmiş** sesli arama</target> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="**e2e encrypted** video call" xml:space="preserve"> <source>**e2e encrypted** video call</source> + <target>**uçtan uca şifrelenmiş** görüntülü arama</target> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="*bold*" xml:space="preserve"> <source>\*bold*</source> + <target>\*kalın*</target> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id=", " xml:space="preserve"> <source>, </source> + <target>, </target> + <note>No comment provided by engineer.</note> + </trans-unit> + <trans-unit id="- connect to [directory service](simplex:/contact#/?v=1-4&smp=smp%3A%2F%2Fu2dS9sG8nMNURyZwqASV4yROM28Er0luVTx5X1CsMrU%3D%40smp4.simplex.im%2FeXSPwqTkKyDO3px4fLf1wx3MvPdjdLW3%23%2F%3Fv%3D1-2%26dh%3DMCowBQYDK2VuAyEAaiv6MkMH44L2TcYrt_CsX3ZvM11WgbMEUn0hkIKTOho%253D%26srv%3Do5vmywmrnaxalvz6wi3zicyftgio6psuvyniis6gco6bp6ekl4cqj4id.onion) (BETA)! - delivery receipts (up to 20 members). - faster and more stable." xml:space="preserve"> + <source>- connect to [directory service](simplex:/contact#/?v=1-4&smp=smp%3A%2F%2Fu2dS9sG8nMNURyZwqASV4yROM28Er0luVTx5X1CsMrU%3D%40smp4.simplex.im%2FeXSPwqTkKyDO3px4fLf1wx3MvPdjdLW3%23%2F%3Fv%3D1-2%26dh%3DMCowBQYDK2VuAyEAaiv6MkMH44L2TcYrt_CsX3ZvM11WgbMEUn0hkIKTOho%253D%26srv%3Do5vmywmrnaxalvz6wi3zicyftgio6psuvyniis6gco6bp6ekl4cqj4id.onion) (BETA)! +- delivery receipts (up to 20 members). +- faster and more stable.</source> + <target>- [dizin hizmeti] 'ne bağlan(simplex:/contact#/?v=1-4&smp=smp%3A%2F%2Fu2dS9sG8nMNURyZwqASV4yROM28Er0luVTx5X1CsMrU%3D%40smp4.simplex.im%2FeXSPwqTkKyDO3px4fLf1wx3MvPdjdLW3%23%2F%3Fv%3D1-2%26dh%3DMCowBQYDK2VuAyEAaiv6MkMH44L2TcYrt_CsX3ZvM11WgbMEUn0hkIKTOho%253D%26srv%3Do5vmywmrnaxalvz6wi3zicyftgio6psuvyniis6gco6bp6ekl4cqj4id.onion) (BETA)! +- çoklu mesaj gönderimi (20 kişiye kadar). +- daha hızlı ve daha stabil.</target> + <note>No comment provided by engineer.</note> + </trans-unit> + <trans-unit id="- more stable message delivery. - a bit better groups. - and more!" xml:space="preserve"> + <source>- more stable message delivery. +- a bit better groups. +- and more!</source> + <target>- daha stabil mesaj gönderimi. +- birazcık daha iyi gruplar. +- ve fazlası!</target> + <note>No comment provided by engineer.</note> + </trans-unit> + <trans-unit id="- optionally notify deleted contacts. - profile names with spaces. - and more!" xml:space="preserve"> + <source>- optionally notify deleted contacts. +- profile names with spaces. +- and more!</source> + <target>- isteğe bağlı olarak silinen kişilere bildirme. +- boşluklu profil adları +- ve fazlası!</target> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="- voice messages up to 5 minutes. - custom time to disappear. - editing history." xml:space="preserve"> <source>- voice messages up to 5 minutes. - custom time to disappear. - editing history.</source> + <target>- 5 dakikaya kadar süren sesli mesajlar. +- mesaj kaybolması için özel zaman. +- düzenleme geçmişi.</target> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="." xml:space="preserve"> <source>.</source> + <target>.</target> <note>No comment provided by engineer.</note> </trans-unit> + <trans-unit id="0 sec" xml:space="preserve"> + <source>0 sec</source> + <target>0 saniye</target> + <note>time to disappear</note> + </trans-unit> <trans-unit id="0s" xml:space="preserve"> <source>0s</source> + <target>0 saniye</target> <note>No comment provided by engineer.</note> </trans-unit> - <trans-unit id="1 day" xml:space="preserve" approved="no"> + <trans-unit id="1 day" xml:space="preserve"> <source>1 day</source> - <target state="translated">1 gün</target> + <target>1 gün</target> <note>time interval</note> </trans-unit> - <trans-unit id="1 hour" xml:space="preserve" approved="no"> + <trans-unit id="1 hour" xml:space="preserve"> <source>1 hour</source> - <target state="translated">1 saat</target> + <target>1 saat</target> <note>time interval</note> </trans-unit> - <trans-unit id="1 minute" xml:space="preserve" approved="no"> + <trans-unit id="1 minute" xml:space="preserve"> <source>1 minute</source> - <target state="translated">1 dakika</target> + <target>1 dakika</target> <note>No comment provided by engineer.</note> </trans-unit> - <trans-unit id="1 month" xml:space="preserve" approved="no"> + <trans-unit id="1 month" xml:space="preserve"> <source>1 month</source> - <target state="translated">1 ay</target> + <target>1 ay</target> <note>time interval</note> </trans-unit> - <trans-unit id="1 week" xml:space="preserve" approved="no"> + <trans-unit id="1 week" xml:space="preserve"> <source>1 week</source> - <target state="translated">1 hafta</target> + <target>1 hafta</target> <note>time interval</note> </trans-unit> - <trans-unit id="1-time link" xml:space="preserve" approved="no"> - <source>1-time link</source> - <target state="translated">tek kullanımlık bağlantı</target> - <note>No comment provided by engineer.</note> - </trans-unit> - <trans-unit id="5 minutes" xml:space="preserve" approved="no"> + <trans-unit id="5 minutes" xml:space="preserve"> <source>5 minutes</source> - <target state="translated">5 dakika</target> + <target>5 dakika</target> <note>No comment provided by engineer.</note> </trans-unit> - <trans-unit id="6" xml:space="preserve" approved="no"> + <trans-unit id="6" xml:space="preserve"> <source>6</source> - <target state="translated">6</target> + <target>6</target> <note>No comment provided by engineer.</note> </trans-unit> - <trans-unit id="30 seconds" xml:space="preserve" approved="no"> + <trans-unit id="30 seconds" xml:space="preserve"> <source>30 seconds</source> - <target state="translated">30 saniye</target> + <target>30 saniye</target> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id=": " xml:space="preserve"> <source>: </source> + <target>: </target> <note>No comment provided by engineer.</note> </trans-unit> - <trans-unit id="<p>Hi!</p> <p><a href="%@">Connect to me via SimpleX Chat</a></p>" xml:space="preserve" approved="no"> + <trans-unit id="<p>Hi!</p> <p><a href="%@">Connect to me via SimpleX Chat</a></p>" xml:space="preserve"> <source><p>Hi!</p> <p><a href="%@">Connect to me via SimpleX Chat</a></p></source> - <target state="translated"><p>Merhaba!</p> + <target><p>Merhaba!</p> <p><a href="%@">SimpleX Chat ile bana bağlanın</a></p></target> <note>email text</note> </trans-unit> - <trans-unit id="A new contact" xml:space="preserve" approved="no"> - <source>A new contact</source> - <target state="translated">Yeni kişi</target> - <note>notification title</note> - </trans-unit> - <trans-unit id="A random profile will be sent to the contact that you received this link from" xml:space="preserve" approved="no"> - <source>A random profile will be sent to the contact that you received this link from</source> - <target state="translated">Bu bağlantıyı aldığınız kişiye rastgele bir profil gönderilecek</target> + <trans-unit id="A few more things" xml:space="preserve"> + <source>A few more things</source> + <target>Birkaç şey daha</target> <note>No comment provided by engineer.</note> </trans-unit> - <trans-unit id="A random profile will be sent to your contact" xml:space="preserve" approved="no"> - <source>A random profile will be sent to your contact</source> - <target state="translated">Kişinize rastgele bir profil gönderilecek</target> + <trans-unit id="A new contact" xml:space="preserve"> + <source>A new contact</source> + <target>Yeni kişi</target> + <note>notification title</note> + </trans-unit> + <trans-unit id="A new random profile will be shared." xml:space="preserve"> + <source>A new random profile will be shared.</source> + <target>Yeni bir rastgele profil paylaşılacak.</target> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="A separate TCP connection will be used **for each chat profile you have in the app**." xml:space="preserve"> <source>A separate TCP connection will be used **for each chat profile you have in the app**.</source> + <target>**uygulamandaki olan her sohbet profili için** ayrı bir TCP bağlantısı kullanılacaktır.</target> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="A separate TCP connection will be used **for each contact and group member**. **Please note**: if you have many connections, your battery and traffic consumption can be substantially higher and some connections may fail." xml:space="preserve"> <source>A separate TCP connection will be used **for each contact and group member**. **Please note**: if you have many connections, your battery and traffic consumption can be substantially higher and some connections may fail.</source> + <target>**uygulamandaki olan her sohbet profili için** ayrı bir TCP bağlantısı kullanılacaktır. +**Lütfen aklınızda bulunsun**: eğer çok fazla bağlantılarınız var ise pil kullanımı ve internet kullanımınız oldukça artabilir ve bazı bağlantılar hatayla karşılaşabilir.</target> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="Abort" xml:space="preserve"> <source>Abort</source> + <target>İptal Et</target> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="Abort changing address" xml:space="preserve"> <source>Abort changing address</source> + <target>Adres değişimini iptal et</target> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="Abort changing address?" xml:space="preserve"> <source>Abort changing address?</source> + <target>Adres değişimi iptal edilsin mi?</target> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="About SimpleX" xml:space="preserve"> <source>About SimpleX</source> + <target>SimpleX Hakkında</target> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="About SimpleX Chat" xml:space="preserve"> <source>About SimpleX Chat</source> + <target>SimpleX Chat hakkında</target> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="About SimpleX address" xml:space="preserve"> <source>About SimpleX address</source> + <target>SimpleX Chat adresi hakkında</target> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="Accent color" xml:space="preserve"> <source>Accent color</source> + <target>Vurgu rengi</target> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="Accept" xml:space="preserve"> <source>Accept</source> + <target>Kabul et</target> <note>accept contact request via notification accept incoming call via notification</note> </trans-unit> - <trans-unit id="Accept contact" xml:space="preserve"> - <source>Accept contact</source> + <trans-unit id="Accept connection request?" xml:space="preserve"> + <source>Accept connection request?</source> + <target>Bağlantı isteği kabul edilsin mi?</target> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="Accept contact request from %@?" xml:space="preserve"> <source>Accept contact request from %@?</source> + <target>%@ 'den gelen iletişim isteği kabul edilsin mi?</target> <note>notification body</note> </trans-unit> <trans-unit id="Accept incognito" xml:space="preserve"> <source>Accept incognito</source> - <note>No comment provided by engineer.</note> + <target>Takma adla kabul et</target> + <note>accept contact request via notification</note> </trans-unit> <trans-unit id="Add address to your profile, so that your contacts can share it with other people. Profile update will be sent to your contacts." xml:space="preserve"> <source>Add address to your profile, so that your contacts can share it with other people. Profile update will be sent to your contacts.</source> + <target>Kişilerinizin başkalarıyla paylaşabilmesi için profilinize adres ekleyin. Profil güncellemesi kişilerinize gönderilecek.</target> + <note>No comment provided by engineer.</note> + </trans-unit> + <trans-unit id="Add contact" xml:space="preserve"> + <source>Add contact</source> + <target>Kişi ekle</target> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="Add preset servers" xml:space="preserve"> <source>Add preset servers</source> + <target>Önceden ayarlanmış sunucu ekle</target> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="Add profile" xml:space="preserve"> <source>Add profile</source> + <target>Profil ekle</target> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="Add servers by scanning QR codes." xml:space="preserve"> <source>Add servers by scanning QR codes.</source> + <target>Karekod taratarak sunucuları ekleyin.</target> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="Add server…" xml:space="preserve"> <source>Add server…</source> + <target>Sunucu ekle…</target> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="Add to another device" xml:space="preserve"> <source>Add to another device</source> + <target>Başka bir cihaza ekle</target> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="Add welcome message" xml:space="preserve"> <source>Add welcome message</source> + <target>Karşılama mesajı ekleyin</target> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="Address" xml:space="preserve"> <source>Address</source> + <target>Adres</target> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="Address change will be aborted. Old receiving address will be used." xml:space="preserve"> <source>Address change will be aborted. Old receiving address will be used.</source> + <target>Adres değişikliği iptal edilecek. Eski alıcı adresi kullanılacaktır.</target> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="Admins can create the links to join groups." xml:space="preserve"> <source>Admins can create the links to join groups.</source> + <target>Yöneticiler gruplara katılmak için bağlantılar oluşturabilir.</target> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="Advanced network settings" xml:space="preserve"> <source>Advanced network settings</source> + <target>GGelişmiş ağ ayarları</target> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="All app data is deleted." xml:space="preserve"> <source>All app data is deleted.</source> + <target>Tüm uygulama verileri silinir.</target> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="All chats and messages will be deleted - this cannot be undone!" xml:space="preserve"> <source>All chats and messages will be deleted - this cannot be undone!</source> + <target>Tüm konuşmalar ve mesajlar silinecektir. Bu, geri alınamaz!</target> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="All data is erased when it is entered." xml:space="preserve"> <source>All data is erased when it is entered.</source> + <target>Kullanıldığında bütün veriler silinir.</target> <note>No comment provided by engineer.</note> </trans-unit> - <trans-unit id="All group members will remain connected." xml:space="preserve" approved="no"> + <trans-unit id="All group members will remain connected." xml:space="preserve"> <source>All group members will remain connected.</source> - <target state="translated">Tüm grup üyeleri bağlı kalacaktır.</target> + <target>Tüm grup üyeleri bağlı kalacaktır.</target> + <note>No comment provided by engineer.</note> + </trans-unit> + <trans-unit id="All messages will be deleted - this cannot be undone!" xml:space="preserve"> + <source>All messages will be deleted - this cannot be undone!</source> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="All messages will be deleted - this cannot be undone! The messages will be deleted ONLY for you." xml:space="preserve"> <source>All messages will be deleted - this cannot be undone! The messages will be deleted ONLY for you.</source> + <target>Tüm mesajlar silinecektir. Bu, geri alınamaz! Mesajlar, YALNIZCA senin için silinecektir.</target> + <note>No comment provided by engineer.</note> + </trans-unit> + <trans-unit id="All new messages from %@ will be hidden!" xml:space="preserve"> + <source>All new messages from %@ will be hidden!</source> + <target>%@ 'den gelen bütün yeni mesajlar saklı olacak!</target> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="All your contacts will remain connected." xml:space="preserve"> <source>All your contacts will remain connected.</source> + <target>Konuştuğun kişilerin tümü bağlı kalacaktır.</target> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="All your contacts will remain connected. Profile update will be sent to your contacts." xml:space="preserve"> <source>All your contacts will remain connected. Profile update will be sent to your contacts.</source> + <target>Tüm kişileriniz bağlı kalacaktır. Profil güncellemesi kişilerinize gönderilecektir.</target> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="Allow" xml:space="preserve"> <source>Allow</source> + <target>İzin ver</target> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="Allow calls only if your contact allows them." xml:space="preserve"> <source>Allow calls only if your contact allows them.</source> + <target>Yalnızca irtibat kişiniz izin veriyorsa aramalara izin verin.</target> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="Allow disappearing messages only if your contact allows it to you." xml:space="preserve"> <source>Allow disappearing messages only if your contact allows it to you.</source> + <target>Eğer kişide izin verirse kaybolan mesajlara izin ver.</target> <note>No comment provided by engineer.</note> </trans-unit> - <trans-unit id="Allow irreversible message deletion only if your contact allows it to you." xml:space="preserve"> - <source>Allow irreversible message deletion only if your contact allows it to you.</source> + <trans-unit id="Allow irreversible message deletion only if your contact allows it to you. (24 hours)" xml:space="preserve"> + <source>Allow irreversible message deletion only if your contact allows it to you. (24 hours)</source> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="Allow message reactions only if your contact allows them." xml:space="preserve"> <source>Allow message reactions only if your contact allows them.</source> + <target>Yalnızca kişin mesaj tepkilerine izin veriyorsa sen de ver.</target> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="Allow message reactions." xml:space="preserve"> <source>Allow message reactions.</source> + <target>Mesaj tepkilerine izin ver.</target> <note>No comment provided by engineer.</note> </trans-unit> - <trans-unit id="Allow sending direct messages to members." xml:space="preserve" approved="no"> + <trans-unit id="Allow sending direct messages to members." xml:space="preserve"> <source>Allow sending direct messages to members.</source> - <target state="translated">Üyelere direkt mesaj göndermeye izin ver.</target> + <target>Üyelere direkt mesaj göndermeye izin ver.</target> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="Allow sending disappearing messages." xml:space="preserve"> <source>Allow sending disappearing messages.</source> + <target>Kendiliğinden yok olan mesajlar göndermeye izin ver.</target> <note>No comment provided by engineer.</note> </trans-unit> - <trans-unit id="Allow to irreversibly delete sent messages." xml:space="preserve"> - <source>Allow to irreversibly delete sent messages.</source> + <trans-unit id="Allow to irreversibly delete sent messages. (24 hours)" xml:space="preserve"> + <source>Allow to irreversibly delete sent messages. (24 hours)</source> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="Allow to send files and media." xml:space="preserve"> <source>Allow to send files and media.</source> + <target>Dosya ve medya göndermeye izin ver.</target> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="Allow to send voice messages." xml:space="preserve"> <source>Allow to send voice messages.</source> + <target>Sesli mesaj göndermeye izin ver.</target> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="Allow voice messages only if your contact allows them." xml:space="preserve"> <source>Allow voice messages only if your contact allows them.</source> + <target>Yalnızca kişiniz sesli mesaj göndermeye izin veriyorsa sen de ver.</target> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="Allow voice messages?" xml:space="preserve"> <source>Allow voice messages?</source> + <target>Sesli mesajlara izin ver?</target> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="Allow your contacts adding message reactions." xml:space="preserve"> <source>Allow your contacts adding message reactions.</source> + <target>Konuştuğun kişilerin mesajlarına tepki eklemesine izin ver.</target> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="Allow your contacts to call you." xml:space="preserve"> <source>Allow your contacts to call you.</source> + <target>Kişilerinin seni aramasına izin ver.</target> <note>No comment provided by engineer.</note> </trans-unit> - <trans-unit id="Allow your contacts to irreversibly delete sent messages." xml:space="preserve"> - <source>Allow your contacts to irreversibly delete sent messages.</source> + <trans-unit id="Allow your contacts to irreversibly delete sent messages. (24 hours)" xml:space="preserve"> + <source>Allow your contacts to irreversibly delete sent messages. (24 hours)</source> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="Allow your contacts to send disappearing messages." xml:space="preserve"> <source>Allow your contacts to send disappearing messages.</source> + <target>Kişilerinizin kaybolan mesajlar göndermesine izin verin.</target> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="Allow your contacts to send voice messages." xml:space="preserve"> <source>Allow your contacts to send voice messages.</source> + <target>Kişilerinizin sesli mesajlar göndermesine izin verin.</target> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="Already connected?" xml:space="preserve"> <source>Already connected?</source> + <target>Zaten bağlandı?</target> + <note>No comment provided by engineer.</note> + </trans-unit> + <trans-unit id="Already connecting!" xml:space="preserve"> + <source>Already connecting!</source> + <target>Zaten bağlanılıyor!</target> + <note>No comment provided by engineer.</note> + </trans-unit> + <trans-unit id="Already joining the group!" xml:space="preserve"> + <source>Already joining the group!</source> + <target>Zaten gruba bağlanılıyor!</target> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="Always use relay" xml:space="preserve"> <source>Always use relay</source> + <target>Her zaman yönlendirici kulan</target> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="An empty chat profile with the provided name is created, and the app opens as usual." xml:space="preserve"> <source>An empty chat profile with the provided name is created, and the app opens as usual.</source> + <target>Verilen adla boş bir sohbet profili oluşturulur ve uygulama her zamanki gibi açılır.</target> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="Answer call" xml:space="preserve"> <source>Answer call</source> + <target>Aramayı cevapla</target> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="App build: %@" xml:space="preserve"> <source>App build: %@</source> + <target>Uygulama sürümü: %@</target> + <note>No comment provided by engineer.</note> + </trans-unit> + <trans-unit id="App encrypts new local files (except videos)." xml:space="preserve"> + <source>App encrypts new local files (except videos).</source> + <target>Uygulama yerel dosyaları şifreler (videolar dışında).</target> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="App icon" xml:space="preserve"> <source>App icon</source> + <target>Uygulama simgesi</target> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="App passcode" xml:space="preserve"> <source>App passcode</source> + <target>Uygulama erişim kodu</target> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="App passcode is replaced with self-destruct passcode." xml:space="preserve"> <source>App passcode is replaced with self-destruct passcode.</source> + <target>Uygulama parolası kendi kendini imha eden parolayla değiştirildi.</target> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="App version" xml:space="preserve"> <source>App version</source> + <target>Uygulama sürümü</target> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="App version: v%@" xml:space="preserve"> <source>App version: v%@</source> + <target>Uygulama sürümü: v%@</target> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="Appearance" xml:space="preserve"> <source>Appearance</source> + <target>Görünüş</target> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="Attach" xml:space="preserve"> <source>Attach</source> + <target>Ekle</target> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="Audio & video calls" xml:space="preserve"> <source>Audio & video calls</source> + <target>Sesli & görüntülü aramalar</target> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="Audio and video calls" xml:space="preserve"> <source>Audio and video calls</source> + <target>Sesli ve görüntülü aramalar</target> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="Audio/video calls" xml:space="preserve"> <source>Audio/video calls</source> + <target>Sesli/görüntülü aramalar</target> <note>chat feature</note> </trans-unit> <trans-unit id="Audio/video calls are prohibited." xml:space="preserve"> <source>Audio/video calls are prohibited.</source> + <target>Sesli/görüntülü aramalar yasaklandı.</target> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="Authentication cancelled" xml:space="preserve"> <source>Authentication cancelled</source> + <target>Kimlik doğrulama iptal edildi</target> <note>PIN entry</note> </trans-unit> <trans-unit id="Authentication failed" xml:space="preserve"> <source>Authentication failed</source> + <target>Kimlik doğrulama başarısız oldu</target> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="Authentication is required before the call is connected, but you may miss calls." xml:space="preserve"> <source>Authentication is required before the call is connected, but you may miss calls.</source> + <target>Kimlik doğrulama aramalara bağlanmadan önce gereklidir, ama aramaları kaçırabilirsin.</target> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="Authentication unavailable" xml:space="preserve"> <source>Authentication unavailable</source> + <target>Kimlik doğrulama kullanım dışı</target> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="Auto-accept" xml:space="preserve"> <source>Auto-accept</source> + <target>Otomatik-kabul et</target> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="Auto-accept contact requests" xml:space="preserve"> <source>Auto-accept contact requests</source> + <target>İletişim isteklerini otomatik kabul et</target> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="Auto-accept images" xml:space="preserve"> <source>Auto-accept images</source> + <target>Fotoğrafları otomatik kabul et</target> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="Back" xml:space="preserve"> <source>Back</source> + <target>Geri</target> + <note>No comment provided by engineer.</note> + </trans-unit> + <trans-unit id="Bad desktop address" xml:space="preserve"> + <source>Bad desktop address</source> + <target>Kötü bilgisayar adresi</target> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="Bad message ID" xml:space="preserve"> <source>Bad message ID</source> + <target>Kötü mesaj kimliği</target> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="Bad message hash" xml:space="preserve"> <source>Bad message hash</source> + <target>Kötü mesaj karması</target> + <note>No comment provided by engineer.</note> + </trans-unit> + <trans-unit id="Better groups" xml:space="preserve"> + <source>Better groups</source> + <target>Daha iyi gruplar</target> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="Better messages" xml:space="preserve"> <source>Better messages</source> + <target>Daha iyi mesajlar</target> + <note>No comment provided by engineer.</note> + </trans-unit> + <trans-unit id="Block" xml:space="preserve"> + <source>Block</source> + <target>Engelle</target> + <note>No comment provided by engineer.</note> + </trans-unit> + <trans-unit id="Block for all" xml:space="preserve"> + <source>Block for all</source> + <note>No comment provided by engineer.</note> + </trans-unit> + <trans-unit id="Block group members" xml:space="preserve"> + <source>Block group members</source> + <target>Grup üyelerini engelle</target> + <note>No comment provided by engineer.</note> + </trans-unit> + <trans-unit id="Block member" xml:space="preserve"> + <source>Block member</source> + <target>Üyeyi engelle</target> + <note>No comment provided by engineer.</note> + </trans-unit> + <trans-unit id="Block member for all?" xml:space="preserve"> + <source>Block member for all?</source> + <note>No comment provided by engineer.</note> + </trans-unit> + <trans-unit id="Block member?" xml:space="preserve"> + <source>Block member?</source> + <target>Üyeyi engelle?</target> + <note>No comment provided by engineer.</note> + </trans-unit> + <trans-unit id="Blocked by admin" xml:space="preserve"> + <source>Blocked by admin</source> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="Both you and your contact can add message reactions." xml:space="preserve"> <source>Both you and your contact can add message reactions.</source> + <target>Sen ve konuştuğun kişi mesaj tepkileri ekleyebilir.</target> <note>No comment provided by engineer.</note> </trans-unit> - <trans-unit id="Both you and your contact can irreversibly delete sent messages." xml:space="preserve"> - <source>Both you and your contact can irreversibly delete sent messages.</source> + <trans-unit id="Both you and your contact can irreversibly delete sent messages. (24 hours)" xml:space="preserve"> + <source>Both you and your contact can irreversibly delete sent messages. (24 hours)</source> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="Both you and your contact can make calls." xml:space="preserve"> <source>Both you and your contact can make calls.</source> + <target>Sen ve konuştuğun kişi aramalar yapabilir.</target> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="Both you and your contact can send disappearing messages." xml:space="preserve"> <source>Both you and your contact can send disappearing messages.</source> + <target>Sen ve konuştuğun kişi kaybolan mesajlar gönderebilir.</target> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="Both you and your contact can send voice messages." xml:space="preserve"> <source>Both you and your contact can send voice messages.</source> + <target>Sen ve konuştuğun kişi sesli mesaj gönderebilir.</target> + <note>No comment provided by engineer.</note> + </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"> + <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>Bulgarca, Fince, Tayca ve Ukraynaca - kullanıcılara ve [Weblate] e teşekkürler! (https://github.com/simplex-chat/simplex-chat/tree/stable#help-translating-simplex-chat)!</target> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="By chat profile (default) or [by connection](https://simplex.chat/blog/20230204-simplex-chat-v4-5-user-chat-profiles.html#transport-isolation) (BETA)." xml:space="preserve"> <source>By chat profile (default) or [by connection](https://simplex.chat/blog/20230204-simplex-chat-v4-5-user-chat-profiles.html#transport-isolation) (BETA).</source> + <target>Sohbet profiline göre (varsayılan) veya [bağlantıya göre](https://simplex.chat/blog/20230204-simplex-chat-v4-5-user-chat-profiles.html#transport-isolation) (BETA).</target> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="Call already ended!" xml:space="preserve"> <source>Call already ended!</source> + <target>Arama çoktan bitti!</target> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="Calls" xml:space="preserve"> <source>Calls</source> + <target>Aramalar</target> <note>No comment provided by engineer.</note> </trans-unit> - <trans-unit id="Can't delete user profile!" xml:space="preserve"> - <source>Can't delete user profile!</source> + <trans-unit id="Camera not available" xml:space="preserve"> + <source>Camera not available</source> + <target>Kamera mevcut değil</target> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="Can't invite contact!" xml:space="preserve"> <source>Can't invite contact!</source> + <target>Kişi davet edilemiyor!</target> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="Can't invite contacts!" xml:space="preserve"> <source>Can't invite contacts!</source> + <target>Kişiler davet edilemiyor!</target> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="Cancel" xml:space="preserve"> <source>Cancel</source> + <target>İptal et</target> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="Cannot access keychain to save database password" xml:space="preserve"> <source>Cannot access keychain to save database password</source> + <target>Veritabanı şifresini kaydetmek için Anahtar Zinciri'ne erişilemiyor</target> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="Cannot receive file" xml:space="preserve"> <source>Cannot receive file</source> + <target>Dosya alınamıyor</target> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="Change" xml:space="preserve"> <source>Change</source> + <target>Değiştir</target> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="Change database passphrase?" xml:space="preserve"> <source>Change database passphrase?</source> + <target>Veritabanı parolasını değiştir?</target> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="Change lock mode" xml:space="preserve"> <source>Change lock mode</source> + <target>Kilit modunu değiştir</target> <note>authentication reason</note> </trans-unit> <trans-unit id="Change member role?" xml:space="preserve"> <source>Change member role?</source> + <target>Üye rolünü değiştir?</target> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="Change passcode" xml:space="preserve"> <source>Change passcode</source> + <target>Şifreyi değiştir</target> <note>authentication reason</note> </trans-unit> <trans-unit id="Change receiving address" xml:space="preserve"> <source>Change receiving address</source> + <target>Alıcı adresini değiştir</target> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="Change receiving address?" xml:space="preserve"> <source>Change receiving address?</source> + <target>Alıcı adresi değiştirilsin mi?</target> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="Change role" xml:space="preserve"> <source>Change role</source> + <target>Rolü değiştir</target> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="Change self-destruct mode" xml:space="preserve"> <source>Change self-destruct mode</source> + <target>Kendini yok etme modunu değiştir</target> <note>authentication reason</note> </trans-unit> <trans-unit id="Change self-destruct passcode" xml:space="preserve"> <source>Change self-destruct passcode</source> + <target>Kendini yok eden parolayı değiştir</target> <note>authentication reason set passcode view</note> </trans-unit> <trans-unit id="Chat archive" xml:space="preserve"> <source>Chat archive</source> + <target>Sohbet arşivi</target> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="Chat console" xml:space="preserve"> <source>Chat console</source> + <target>Sohbet konsolu</target> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="Chat database" xml:space="preserve"> <source>Chat database</source> + <target>Sohbet veritabanı</target> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="Chat database deleted" xml:space="preserve"> <source>Chat database deleted</source> + <target>Sohbet veritabanı silindi</target> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="Chat database imported" xml:space="preserve"> <source>Chat database imported</source> + <target>Sohbet veritabanı içe aktarıldı</target> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="Chat is running" xml:space="preserve"> <source>Chat is running</source> + <target>Sohbet çalışıyor</target> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="Chat is stopped" xml:space="preserve"> <source>Chat is stopped</source> + <target>Sohbet durdu</target> + <note>No comment provided by engineer.</note> + </trans-unit> + <trans-unit id="Chat is stopped. If you already used this database on another device, you should transfer it back before starting chat." xml:space="preserve"> + <source>Chat is stopped. If you already used this database on another device, you should transfer it back before starting chat.</source> + <target>Sohbet durduruldu. Bu veritabanını zaten başka bir cihazda kullandıysanız, sohbete başlamadan önce onu geri aktarmalısınız.</target> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="Chat preferences" xml:space="preserve"> <source>Chat preferences</source> + <target>Sohbet tercihleri</target> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="Chats" xml:space="preserve"> <source>Chats</source> + <target>Sohbetler</target> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="Check server address and try again." xml:space="preserve"> <source>Check server address and try again.</source> + <target>Sunucu adresini kontrol edip tekrar deneyin.</target> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="Chinese and Spanish interface" xml:space="preserve"> <source>Chinese and Spanish interface</source> + <target>Çince ve İspanyolca arayüz</target> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="Choose file" xml:space="preserve"> <source>Choose file</source> + <target>Dosya seç</target> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="Choose from library" xml:space="preserve"> <source>Choose from library</source> + <target>Kütüphaneden seç</target> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="Clear" xml:space="preserve"> <source>Clear</source> + <target>Temizle</target> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="Clear conversation" xml:space="preserve"> <source>Clear conversation</source> + <target>Sohbeti temizle</target> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="Clear conversation?" xml:space="preserve"> <source>Clear conversation?</source> + <target>Sohbet temizlensin mi?</target> + <note>No comment provided by engineer.</note> + </trans-unit> + <trans-unit id="Clear private notes?" xml:space="preserve"> + <source>Clear private notes?</source> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="Clear verification" xml:space="preserve"> <source>Clear verification</source> + <target>Doğrulamayı temizle</target> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="Colors" xml:space="preserve"> <source>Colors</source> + <target>Renkler</target> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="Compare file" xml:space="preserve"> <source>Compare file</source> + <target>Dosya karşılaştır</target> <note>server test step</note> </trans-unit> <trans-unit id="Compare security codes with your contacts." xml:space="preserve"> <source>Compare security codes with your contacts.</source> + <target>Güvenlik kodlarını kişilerinle karşılaştır.</target> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="Configure ICE servers" xml:space="preserve"> <source>Configure ICE servers</source> + <target>ICE sunucularını ayarla</target> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="Confirm" xml:space="preserve"> <source>Confirm</source> + <target>Onayla</target> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="Confirm Passcode" xml:space="preserve"> <source>Confirm Passcode</source> + <target>Parolayı onayla</target> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="Confirm database upgrades" xml:space="preserve"> <source>Confirm database upgrades</source> + <target>Veritabanı geliştirmelerini onayla</target> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="Confirm new passphrase…" xml:space="preserve"> <source>Confirm new passphrase…</source> + <target>Yeni parolayı onayla…</target> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="Confirm password" xml:space="preserve"> <source>Confirm password</source> + <target>Şifreyi onayla</target> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="Connect" xml:space="preserve"> <source>Connect</source> + <target>Bağlan</target> <note>server test step</note> </trans-unit> - <trans-unit id="Connect via contact link?" xml:space="preserve"> - <source>Connect via contact link?</source> + <trans-unit id="Connect automatically" xml:space="preserve"> + <source>Connect automatically</source> + <target>Otomatik olarak bağlan</target> <note>No comment provided by engineer.</note> </trans-unit> - <trans-unit id="Connect via group link?" xml:space="preserve"> - <source>Connect via group link?</source> + <trans-unit id="Connect incognito" xml:space="preserve"> + <source>Connect incognito</source> + <target>Gizli bağlan</target> + <note>No comment provided by engineer.</note> + </trans-unit> + <trans-unit id="Connect to desktop" xml:space="preserve"> + <source>Connect to desktop</source> + <target>Bilgisayara bağlan</target> + <note>No comment provided by engineer.</note> + </trans-unit> + <trans-unit id="Connect to yourself?" xml:space="preserve"> + <source>Connect to yourself?</source> + <target>Kendine mi bağlanacaksın?</target> + <note>No comment provided by engineer.</note> + </trans-unit> + <trans-unit id="Connect to yourself? This is your own SimpleX address!" xml:space="preserve"> + <source>Connect to yourself? +This is your own SimpleX address!</source> + <target>Kendine mi bağlanacaksın? +Bu senin kendi SimpleX adresin!</target> + <note>No comment provided by engineer.</note> + </trans-unit> + <trans-unit id="Connect to yourself? This is your own one-time link!" xml:space="preserve"> + <source>Connect to yourself? +This is your own one-time link!</source> + <target>Kendine mi bağlanacaksın? +Bu senin kendi tek kullanımlık bağlantın!</target> + <note>No comment provided by engineer.</note> + </trans-unit> + <trans-unit id="Connect via contact address" xml:space="preserve"> + <source>Connect via contact address</source> + <target>Kişi adresi aracılığıyla bağlan</target> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="Connect via link" xml:space="preserve"> <source>Connect via link</source> + <target>Bağlantı aracılığıyla bağlan</target> <note>No comment provided by engineer.</note> </trans-unit> - <trans-unit id="Connect via link / QR code" xml:space="preserve"> - <source>Connect via link / QR code</source> + <trans-unit id="Connect via one-time link" xml:space="preserve"> + <source>Connect via one-time link</source> + <target>Tek kullanımlık bağlantı aracılığıyla bağlan</target> <note>No comment provided by engineer.</note> </trans-unit> - <trans-unit id="Connect via one-time link?" xml:space="preserve"> - <source>Connect via one-time link?</source> + <trans-unit id="Connect with %@" xml:space="preserve"> + <source>Connect with %@</source> + <target>%@ ile bağlan</target> + <note>No comment provided by engineer.</note> + </trans-unit> + <trans-unit id="Connected desktop" xml:space="preserve"> + <source>Connected desktop</source> + <target>Bilgisayara bağlandı</target> + <note>No comment provided by engineer.</note> + </trans-unit> + <trans-unit id="Connected to desktop" xml:space="preserve"> + <source>Connected to desktop</source> + <target>Bilgisayara bağlanıldı</target> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="Connecting server…" xml:space="preserve"> <source>Connecting to server…</source> + <target>Sunucuya bağlanıyor…</target> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="Connecting server… (error: %@)" xml:space="preserve"> <source>Connecting to server… (error: %@)</source> + <target>Sunucuya bağlanıyor…(hata:%@)</target> + <note>No comment provided by engineer.</note> + </trans-unit> + <trans-unit id="Connecting to desktop" xml:space="preserve"> + <source>Connecting to desktop</source> + <target>Bilgisayara bağlanıyor</target> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="Connection" xml:space="preserve"> <source>Connection</source> + <target>Bağlantı</target> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="Connection error" xml:space="preserve"> <source>Connection error</source> + <target>Bağlantı hatası</target> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="Connection error (AUTH)" xml:space="preserve"> <source>Connection error (AUTH)</source> - <note>No comment provided by engineer.</note> - </trans-unit> - <trans-unit id="Connection request" xml:space="preserve"> - <source>Connection request</source> + <target>Bağlantı hatası (DOĞRULAMA)</target> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="Connection request sent!" xml:space="preserve"> <source>Connection request sent!</source> + <target>Bağlantı daveti gönderildi!</target> + <note>No comment provided by engineer.</note> + </trans-unit> + <trans-unit id="Connection terminated" xml:space="preserve"> + <source>Connection terminated</source> + <target>Bağlantı sonlandırılmış</target> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="Connection timeout" xml:space="preserve"> <source>Connection timeout</source> + <target>Bağlantı süresi geçmiş</target> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="Contact allows" xml:space="preserve"> <source>Contact allows</source> + <target>Kişi izin veriyor</target> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="Contact already exists" xml:space="preserve"> <source>Contact already exists</source> - <note>No comment provided by engineer.</note> - </trans-unit> - <trans-unit id="Contact and all messages will be deleted - this cannot be undone!" xml:space="preserve"> - <source>Contact and all messages will be deleted - this cannot be undone!</source> + <target>Kişi zaten mevcut</target> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="Contact hidden:" xml:space="preserve"> <source>Contact hidden:</source> + <target>Kişi gizli:</target> <note>notification</note> </trans-unit> <trans-unit id="Contact is connected" xml:space="preserve"> <source>Contact is connected</source> + <target>Kişi bağlandı</target> <note>notification</note> </trans-unit> <trans-unit id="Contact is not connected yet!" xml:space="preserve"> <source>Contact is not connected yet!</source> + <target>Kişi şuan bağlanmadı!</target> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="Contact name" xml:space="preserve"> <source>Contact name</source> + <target>Kişi adı</target> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="Contact preferences" xml:space="preserve"> <source>Contact preferences</source> + <target>Kişi tercihleri</target> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="Contacts" xml:space="preserve"> <source>Contacts</source> + <target>Kişiler</target> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="Contacts can mark messages for deletion; you will be able to view them." xml:space="preserve"> <source>Contacts can mark messages for deletion; you will be able to view them.</source> + <target>Kişiler silinmesi için mesajları işaretleyebilir; onları görüntüleyebilirsin.</target> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="Continue" xml:space="preserve"> <source>Continue</source> + <target>Devam et</target> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="Copy" xml:space="preserve"> <source>Copy</source> + <target>Kopyala</target> <note>chat item action</note> </trans-unit> <trans-unit id="Core version: v%@" xml:space="preserve"> <source>Core version: v%@</source> + <target>Çekirdek sürümü: v%@</target> + <note>No comment provided by engineer.</note> + </trans-unit> + <trans-unit id="Correct name to %@?" xml:space="preserve"> + <source>Correct name to %@?</source> + <target>İsim %@ olarak düzeltilsin mi?</target> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="Create" xml:space="preserve"> <source>Create</source> + <target>Oluştur</target> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="Create SimpleX address" xml:space="preserve"> <source>Create SimpleX address</source> + <target>SimpleX adresi oluştur</target> + <note>No comment provided by engineer.</note> + </trans-unit> + <trans-unit id="Create a group using a random profile." xml:space="preserve"> + <source>Create a group using a random profile.</source> + <target>Rasgele profil kullanarak grup oluştur.</target> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="Create an address to let people connect with you." xml:space="preserve"> <source>Create an address to let people connect with you.</source> + <target>İnsanların seninle bağlanması için bir adres oluştur.</target> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="Create file" xml:space="preserve"> <source>Create file</source> + <target>Dosya oluştur</target> <note>server test step</note> </trans-unit> + <trans-unit id="Create group" xml:space="preserve"> + <source>Create group</source> + <target>Grup oluştur</target> + <note>No comment provided by engineer.</note> + </trans-unit> <trans-unit id="Create group link" xml:space="preserve"> <source>Create group link</source> + <target>Grup bağlantısı oluştur</target> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="Create link" xml:space="preserve"> <source>Create link</source> + <target>Bağlantı oluştur</target> <note>No comment provided by engineer.</note> </trans-unit> - <trans-unit id="Create one-time invitation link" xml:space="preserve"> - <source>Create one-time invitation link</source> + <trans-unit id="Create new profile in [desktop app](https://simplex.chat/downloads/). 💻" xml:space="preserve"> + <source>Create new profile in [desktop app](https://simplex.chat/downloads/). 💻</source> + <target>[bilgisayar uygulaması] nda yeni bir profil oluştur(https://simplex.chat/downloads/). 💻</target> + <note>No comment provided by engineer.</note> + </trans-unit> + <trans-unit id="Create profile" xml:space="preserve"> + <source>Create profile</source> + <target>Profil oluştur</target> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="Create queue" xml:space="preserve"> <source>Create queue</source> + <target>Sıra oluştur</target> <note>server test step</note> </trans-unit> <trans-unit id="Create secret group" xml:space="preserve"> <source>Create secret group</source> + <target>Gizli grup oluştur</target> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="Create your profile" xml:space="preserve"> <source>Create your profile</source> + <target>Profilini oluştur</target> <note>No comment provided by engineer.</note> </trans-unit> + <trans-unit id="Created at" xml:space="preserve"> + <source>Created at</source> + <note>No comment provided by engineer.</note> + </trans-unit> + <trans-unit id="Created at: %@" xml:space="preserve"> + <source>Created at: %@</source> + <note>copied message info</note> + </trans-unit> <trans-unit id="Created on %@" xml:space="preserve"> <source>Created on %@</source> + <target>%@ de oluşturuldu</target> + <note>No comment provided by engineer.</note> + </trans-unit> + <trans-unit id="Creating link…" xml:space="preserve"> + <source>Creating link…</source> + <target>Link oluşturuluyor…</target> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="Current Passcode" xml:space="preserve"> <source>Current Passcode</source> + <target>Şu anki şifre</target> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="Current passphrase…" xml:space="preserve"> <source>Current passphrase…</source> + <target>Şu anki parola…</target> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="Currently maximum supported file size is %@." xml:space="preserve"> <source>Currently maximum supported file size is %@.</source> + <target>Şu anki maksimum desteklenen dosya boyutu %@ kadardır.</target> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="Custom time" xml:space="preserve"> <source>Custom time</source> + <target>Özel saat</target> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="Dark" xml:space="preserve"> <source>Dark</source> + <target>Karanlık</target> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="Database ID" xml:space="preserve"> <source>Database ID</source> + <target>Veritabanı kimliği</target> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="Database ID: %d" xml:space="preserve"> <source>Database ID: %d</source> + <target>Veritabanı kimliği: %d</target> <note>copied message info</note> </trans-unit> <trans-unit id="Database IDs and Transport isolation option." xml:space="preserve"> <source>Database IDs and Transport isolation option.</source> + <target>Veritabanı kimlikleri ve Taşıma izolasyonu seçeneği.</target> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="Database downgrade" xml:space="preserve"> <source>Database downgrade</source> + <target>Veritabanı sürüm düşürme</target> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="Database encrypted!" xml:space="preserve"> <source>Database encrypted!</source> + <target>Veritabanı şifrelendi!</target> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="Database encryption passphrase will be updated and stored in the keychain. " xml:space="preserve"> <source>Database encryption passphrase will be updated and stored in the keychain. </source> + <target>Veritabanı şifreleme parolası güncellenecek ve Anahtar Zinciri'nde saklanacaktır. +</target> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="Database encryption passphrase will be updated. " xml:space="preserve"> <source>Database encryption passphrase will be updated. </source> + <target>Veritabanı şifreleme parolası güncellenecektir. +</target> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="Database error" xml:space="preserve"> <source>Database error</source> + <target>Veritabanı hatası</target> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="Database is encrypted using a random passphrase, you can change it." xml:space="preserve"> <source>Database is encrypted using a random passphrase, you can change it.</source> + <target>Veritabanı rastgele bir parola kullanılarak şifrelenir, bunu değiştirebilirsiniz.</target> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="Database is encrypted using a random passphrase. Please change it before exporting." xml:space="preserve"> <source>Database is encrypted using a random passphrase. Please change it before exporting.</source> + <target>Veritabanı rastgele bir parola kullanılarak şifrelenir. Lütfen dışa aktarmadan önce değiştirin.</target> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="Database passphrase" xml:space="preserve"> <source>Database passphrase</source> + <target>Veritabanı parolası</target> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="Database passphrase & export" xml:space="preserve"> <source>Database passphrase & export</source> + <target>Veritabanı parolası ve dışa aktarma</target> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="Database passphrase is different from saved in the keychain." xml:space="preserve"> <source>Database passphrase is different from saved in the keychain.</source> + <target>Veritabanı parolası Anahtar Zinciri'nde kayıtlı olandan farklıdır.</target> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="Database passphrase is required to open chat." xml:space="preserve"> <source>Database passphrase is required to open chat.</source> + <target>Sohbeti açmak için veritabanı parolası gereklidir.</target> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="Database upgrade" xml:space="preserve"> <source>Database upgrade</source> + <target>Veritabanı yükseltmesi</target> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="Database will be encrypted and the passphrase stored in the keychain. " xml:space="preserve"> <source>Database will be encrypted and the passphrase stored in the keychain. </source> + <target>Veritabanı şifrelenecek ve parola Anahtar Zinciri'nde saklanacaktır. +</target> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="Database will be encrypted. " xml:space="preserve"> <source>Database will be encrypted. </source> + <target>Veritabanı şifrelenecektir. +</target> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="Database will be migrated when the app restarts" xml:space="preserve"> <source>Database will be migrated when the app restarts</source> + <target>Uygulama yeniden başlatıldığında veritabanı taşınacaktır</target> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="Decentralized" xml:space="preserve"> <source>Decentralized</source> + <target>Merkezi Olmayan</target> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="Decryption error" xml:space="preserve"> <source>Decryption error</source> + <target>Şifre çözme hatası</target> <note>message decrypt error item</note> </trans-unit> <trans-unit id="Delete" xml:space="preserve"> <source>Delete</source> + <target>Sil</target> <note>chat item action</note> </trans-unit> + <trans-unit id="Delete %lld messages?" xml:space="preserve"> + <source>Delete %lld messages?</source> + <target>%lld mesajları silinsin mi?</target> + <note>No comment provided by engineer.</note> + </trans-unit> <trans-unit id="Delete Contact" xml:space="preserve"> <source>Delete Contact</source> + <target>Kişiyi sil</target> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="Delete address" xml:space="preserve"> <source>Delete address</source> + <target>Adresi sil</target> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="Delete address?" xml:space="preserve"> <source>Delete address?</source> + <target>Adres silinsin mi?</target> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="Delete after" xml:space="preserve"> <source>Delete after</source> + <target>Sonra sil</target> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="Delete all files" xml:space="preserve"> <source>Delete all files</source> + <target>Bütün dosyaları sil</target> + <note>No comment provided by engineer.</note> + </trans-unit> + <trans-unit id="Delete and notify contact" xml:space="preserve"> + <source>Delete and notify contact</source> + <target>Sil ve kişiye bildir</target> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="Delete archive" xml:space="preserve"> <source>Delete archive</source> + <target>Arşivi sil</target> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="Delete chat archive?" xml:space="preserve"> <source>Delete chat archive?</source> + <target>Sohbet arşivi silinsin mi?</target> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="Delete chat profile" xml:space="preserve"> <source>Delete chat profile</source> + <target>Sohbet profilini sil</target> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="Delete chat profile?" xml:space="preserve"> <source>Delete chat profile?</source> + <target>Sohbet profili silinsin mi?</target> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="Delete connection" xml:space="preserve"> <source>Delete connection</source> + <target>Bağlantıyı sil</target> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="Delete contact" xml:space="preserve"> <source>Delete contact</source> + <target>Kişiyi sil</target> <note>No comment provided by engineer.</note> </trans-unit> - <trans-unit id="Delete contact?" xml:space="preserve"> - <source>Delete contact?</source> + <trans-unit id="Delete contact? This cannot be undone!" xml:space="preserve"> + <source>Delete contact? +This cannot be undone!</source> + <target>Kişi silinsin mi? +Bu geri alınamaz!</target> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="Delete database" xml:space="preserve"> <source>Delete database</source> + <target>Veritabanını sil</target> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="Delete file" xml:space="preserve"> <source>Delete file</source> + <target>Dosyayı sil</target> <note>server test step</note> </trans-unit> <trans-unit id="Delete files and media?" xml:space="preserve"> <source>Delete files and media?</source> + <target>Dosyalar ve medya silinsin mi?</target> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="Delete files for all chat profiles" xml:space="preserve"> <source>Delete files for all chat profiles</source> + <target>Bütün sohbet profilleri için dosyaları sil</target> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="Delete for everyone" xml:space="preserve"> <source>Delete for everyone</source> + <target>Herkesten sil</target> <note>chat feature</note> </trans-unit> <trans-unit id="Delete for me" xml:space="preserve"> <source>Delete for me</source> + <target>Benden sil</target> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="Delete group" xml:space="preserve"> <source>Delete group</source> + <target>Grubu sil</target> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="Delete group?" xml:space="preserve"> <source>Delete group?</source> + <target>Grup silinsin mi?</target> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="Delete invitation" xml:space="preserve"> <source>Delete invitation</source> + <target>Daveti sil</target> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="Delete link" xml:space="preserve"> <source>Delete link</source> + <target>Bağlantıyı sil</target> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="Delete link?" xml:space="preserve"> <source>Delete link?</source> + <target>Bağlantı silinsin mi?</target> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="Delete member message?" xml:space="preserve"> <source>Delete member message?</source> + <target>Kişinin mesajı silinsin mi?</target> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="Delete message?" xml:space="preserve"> <source>Delete message?</source> + <target>Mesaj silinsin mi?</target> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="Delete messages" xml:space="preserve"> <source>Delete messages</source> + <target>Mesajları sil</target> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="Delete messages after" xml:space="preserve"> <source>Delete messages after</source> + <target>Mesajları sonra sil</target> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="Delete old database" xml:space="preserve"> <source>Delete old database</source> + <target>Eski veritabanını sil</target> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="Delete old database?" xml:space="preserve"> <source>Delete old database?</source> + <target>Eski veritabanı silinsin mi?</target> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="Delete pending connection" xml:space="preserve"> <source>Delete pending connection</source> + <target>Bekleyen bağlantıyı sil</target> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="Delete pending connection?" xml:space="preserve"> <source>Delete pending connection?</source> + <target>Bekleyen bağlantı silinsin mi?</target> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="Delete profile" xml:space="preserve"> <source>Delete profile</source> + <target>Profili sil</target> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="Delete queue" xml:space="preserve"> <source>Delete queue</source> + <target>Sırayı sil</target> <note>server test step</note> </trans-unit> <trans-unit id="Delete user profile?" xml:space="preserve"> <source>Delete user profile?</source> + <target>Kullanıcı profili silinsin mi?</target> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="Deleted at" xml:space="preserve"> <source>Deleted at</source> + <target>de silindi</target> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="Deleted at: %@" xml:space="preserve"> <source>Deleted at: %@</source> + <target>%@ de silindi</target> <note>copied message info</note> </trans-unit> + <trans-unit id="Delivery" xml:space="preserve"> + <source>Delivery</source> + <target>Teslimat</target> + <note>No comment provided by engineer.</note> + </trans-unit> <trans-unit id="Delivery receipts are disabled!" xml:space="preserve"> <source>Delivery receipts are disabled!</source> - <note>No comment provided by engineer.</note> - </trans-unit> - <trans-unit id="Delivery receipts will be enabled for all contacts in all visible chat profiles." xml:space="preserve"> - <source>Delivery receipts will be enabled for all contacts in all visible chat profiles.</source> - <note>No comment provided by engineer.</note> - </trans-unit> - <trans-unit id="Delivery receipts will be enabled for all contacts." xml:space="preserve"> - <source>Delivery receipts will be enabled for all contacts.</source> + <target>Mesaj gönderim bilgisi devre dışı!</target> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="Delivery receipts!" xml:space="preserve"> <source>Delivery receipts!</source> + <target>Mesaj gönderildi bilgisi!</target> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="Description" xml:space="preserve"> <source>Description</source> + <target>Açıklama</target> + <note>No comment provided by engineer.</note> + </trans-unit> + <trans-unit id="Desktop address" xml:space="preserve"> + <source>Desktop address</source> + <target>Bilgisayar adresi</target> + <note>No comment provided by engineer.</note> + </trans-unit> + <trans-unit id="Desktop app version %@ is not compatible with this app." xml:space="preserve"> + <source>Desktop app version %@ is not compatible with this app.</source> + <target>Masaüstü uygulaması sürümü %@ bu uygulama ile uyumlu değildir.</target> + <note>No comment provided by engineer.</note> + </trans-unit> + <trans-unit id="Desktop devices" xml:space="preserve"> + <source>Desktop devices</source> + <target>Bilgisayar cihazları</target> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="Develop" xml:space="preserve"> <source>Develop</source> + <target>Geliştir</target> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="Developer tools" xml:space="preserve"> <source>Developer tools</source> + <target>Geliştirici araçları</target> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="Device" xml:space="preserve"> <source>Device</source> + <target>Cihaz</target> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="Device authentication is disabled. Turning off SimpleX Lock." xml:space="preserve"> <source>Device authentication is disabled. Turning off SimpleX Lock.</source> + <target>Cihaz kimlik doğrulaması devre dışı. SimpleX Kilidi kapatılıyor.</target> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="Device authentication is not enabled. You can turn on SimpleX Lock via Settings, once you enable device authentication." xml:space="preserve"> <source>Device authentication is not enabled. You can turn on SimpleX Lock via Settings, once you enable device authentication.</source> + <target>Cihaz kimlik doğrulaması etkin değil. Cihaz kimlik doğrulamasını etkinleştirdikten sonra SimpleX Kilidini Ayarlar üzerinden açabilirsiniz.</target> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="Different names, avatars and transport isolation." xml:space="preserve"> <source>Different names, avatars and transport isolation.</source> + <target>Farklı isimler, profil fotoğrafları ve taşıma izolasyonu.</target> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="Direct messages" xml:space="preserve"> <source>Direct messages</source> + <target>Doğrudan mesajlar</target> <note>chat feature</note> </trans-unit> - <trans-unit id="Direct messages between members are prohibited in this group." xml:space="preserve" approved="no"> + <trans-unit id="Direct messages between members are prohibited in this group." xml:space="preserve"> <source>Direct messages between members are prohibited in this group.</source> - <target state="translated">Bu grupta üyeler arasında direkt mesajlaşma yasaktır.</target> + <target>Bu grupta üyeler arasında direkt mesajlaşma yasaktır.</target> + <note>No comment provided by engineer.</note> + </trans-unit> + <trans-unit id="Disable (keep overrides)" xml:space="preserve"> + <source>Disable (keep overrides)</source> + <target>Devre dışı bırak (geçersiz kılmaları koru)</target> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="Disable SimpleX Lock" xml:space="preserve"> <source>Disable SimpleX Lock</source> + <target>SimpleX Kilidini devre dışı bırak</target> <note>authentication reason</note> </trans-unit> + <trans-unit id="Disable for all" xml:space="preserve"> + <source>Disable for all</source> + <target>Herkes için devre dışı bırak</target> + <note>No comment provided by engineer.</note> + </trans-unit> <trans-unit id="Disappearing message" xml:space="preserve"> <source>Disappearing message</source> + <target>Kaybolan mesaj</target> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="Disappearing messages" xml:space="preserve"> <source>Disappearing messages</source> + <target>Kaybolan mesajlar</target> <note>chat feature</note> </trans-unit> <trans-unit id="Disappearing messages are prohibited in this chat." xml:space="preserve"> <source>Disappearing messages are prohibited in this chat.</source> + <target>Kaybolan mesajlar bu sohbette yasaklanmış.</target> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="Disappearing messages are prohibited in this group." xml:space="preserve"> <source>Disappearing messages are prohibited in this group.</source> + <target>Kaybolan mesajlar bu grupta yasaklanmış.</target> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="Disappears at" xml:space="preserve"> <source>Disappears at</source> + <target>da kaybolur</target> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="Disappears at: %@" xml:space="preserve"> <source>Disappears at: %@</source> + <target>%@ da kaybolur</target> <note>copied message info</note> </trans-unit> <trans-unit id="Disconnect" xml:space="preserve"> <source>Disconnect</source> + <target>Bağlantıyı kes</target> <note>server test step</note> </trans-unit> - <trans-unit id="Display name" xml:space="preserve"> - <source>Display name</source> + <trans-unit id="Disconnect desktop?" xml:space="preserve"> + <source>Disconnect desktop?</source> + <target>Bilgisayarla bağlantı kesilsin mi?</target> <note>No comment provided by engineer.</note> </trans-unit> - <trans-unit id="Display name:" xml:space="preserve"> - <source>Display name:</source> + <trans-unit id="Discover and join groups" xml:space="preserve"> + <source>Discover and join groups</source> + <target>Keşfet ve gruplara katıl</target> + <note>No comment provided by engineer.</note> + </trans-unit> + <trans-unit id="Discover via local network" xml:space="preserve"> + <source>Discover via local network</source> + <target>Yerel ağ aracılığıyla keşfet</target> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="Do NOT use SimpleX for emergency calls." xml:space="preserve"> <source>Do NOT use SimpleX for emergency calls.</source> + <target>Acil aramalar için SimpleX'i KULLANMAYIN.</target> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="Do it later" xml:space="preserve"> <source>Do it later</source> + <target>Sonra yap</target> + <note>No comment provided by engineer.</note> + </trans-unit> + <trans-unit id="Do not send history to new members." xml:space="preserve"> + <source>Do not send history to new members.</source> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="Don't create address" xml:space="preserve"> <source>Don't create address</source> + <target>Adres oluşturma</target> + <note>No comment provided by engineer.</note> + </trans-unit> + <trans-unit id="Don't enable" xml:space="preserve"> + <source>Don't enable</source> + <target>Etkinleştirme</target> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="Don't show again" xml:space="preserve"> <source>Don't show again</source> + <target>Yeniden gösterme</target> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="Downgrade and open chat" xml:space="preserve"> <source>Downgrade and open chat</source> + <target>Sürüm düşür ve sohbeti aç</target> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="Download file" xml:space="preserve"> <source>Download file</source> + <target>Dosya indir</target> <note>server test step</note> </trans-unit> <trans-unit id="Duplicate display name!" xml:space="preserve"> <source>Duplicate display name!</source> + <target>Yinelenen görünen ad!</target> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="Duration" xml:space="preserve"> <source>Duration</source> + <target>Süre</target> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="Edit" xml:space="preserve"> <source>Edit</source> + <target>Düzenle</target> <note>chat item action</note> </trans-unit> <trans-unit id="Edit group profile" xml:space="preserve"> <source>Edit group profile</source> + <target>Grup profilini düzenle</target> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="Enable" xml:space="preserve"> <source>Enable</source> + <target>Etkinleştir</target> + <note>No comment provided by engineer.</note> + </trans-unit> + <trans-unit id="Enable (keep overrides)" xml:space="preserve"> + <source>Enable (keep overrides)</source> + <target>Etkinleştir (geçersiz kılmaları koru)</target> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="Enable SimpleX Lock" xml:space="preserve"> <source>Enable SimpleX Lock</source> + <target>SimpleX Kilidini etkinleştir</target> <note>authentication reason</note> </trans-unit> <trans-unit id="Enable TCP keep-alive" xml:space="preserve"> <source>Enable TCP keep-alive</source> + <target>TCP canlı tutmayı etkinleştir</target> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="Enable automatic message deletion?" xml:space="preserve"> <source>Enable automatic message deletion?</source> + <target>Otomatik mesaj silme etkinleştirilsin mi?</target> + <note>No comment provided by engineer.</note> + </trans-unit> + <trans-unit id="Enable camera access" xml:space="preserve"> + <source>Enable camera access</source> + <target>Kamera erişimini etkinleştir</target> + <note>No comment provided by engineer.</note> + </trans-unit> + <trans-unit id="Enable for all" xml:space="preserve"> + <source>Enable for all</source> + <target>Herkes için etkinleştir</target> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="Enable instant notifications?" xml:space="preserve"> <source>Enable instant notifications?</source> - <note>No comment provided by engineer.</note> - </trans-unit> - <trans-unit id="Enable later via Settings" xml:space="preserve"> - <source>Enable later via Settings</source> + <target>Anlık bildirimler etkinleştirilsin mi?</target> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="Enable lock" xml:space="preserve"> <source>Enable lock</source> + <target>Kilidi etkinleştir</target> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="Enable notifications" xml:space="preserve"> <source>Enable notifications</source> + <target>Bildirimleri etkinleştir</target> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="Enable periodic notifications?" xml:space="preserve"> <source>Enable periodic notifications?</source> + <target>Periyodik bildirimler etkinleştirilsin mi?</target> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="Enable self-destruct" xml:space="preserve"> <source>Enable self-destruct</source> + <target>Kendini imhayı etkinleştir</target> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="Enable self-destruct passcode" xml:space="preserve"> <source>Enable self-destruct passcode</source> + <target>Kendini imha şifresini etkinleştir</target> <note>set passcode view</note> </trans-unit> <trans-unit id="Encrypt" xml:space="preserve"> <source>Encrypt</source> + <target>Şifreleme</target> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="Encrypt database?" xml:space="preserve"> <source>Encrypt database?</source> + <target>Veritabanı şifrelensin mi?</target> + <note>No comment provided by engineer.</note> + </trans-unit> + <trans-unit id="Encrypt local files" xml:space="preserve"> + <source>Encrypt local files</source> + <target>Yerel dosyaları şifrele</target> + <note>No comment provided by engineer.</note> + </trans-unit> + <trans-unit id="Encrypt stored files & media" xml:space="preserve"> + <source>Encrypt stored files & media</source> + <target>Saklanan dosyaları ve medyayı şifreleyin</target> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="Encrypted database" xml:space="preserve"> <source>Encrypted database</source> + <target>Şifrelenmiş veritabanı</target> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="Encrypted message or another event" xml:space="preserve"> <source>Encrypted message or another event</source> + <target>Şifrelenmiş mesaj veya başka bir etkinlik</target> + <note>notification</note> + </trans-unit> + <trans-unit id="Encrypted message: app is stopped" xml:space="preserve"> + <source>Encrypted message: app is stopped</source> + <target>Şifrelenmiş mesaj: uygulama durdu</target> <note>notification</note> </trans-unit> <trans-unit id="Encrypted message: database error" xml:space="preserve"> <source>Encrypted message: database error</source> + <target>Şifrelenmiş mesaj: veritabanı hatası</target> <note>notification</note> </trans-unit> <trans-unit id="Encrypted message: database migration error" xml:space="preserve"> <source>Encrypted message: database migration error</source> + <target>Şifrelenmiş mesaj: veritabanı taşıma hatası</target> <note>notification</note> </trans-unit> <trans-unit id="Encrypted message: keychain error" xml:space="preserve"> <source>Encrypted message: keychain error</source> + <target>Şifrelenmiş mesaj: Anahtar Zinciri hatası</target> <note>notification</note> </trans-unit> <trans-unit id="Encrypted message: no passphrase" xml:space="preserve"> <source>Encrypted message: no passphrase</source> + <target>Şifrelenmiş mesaj: parola yok</target> <note>notification</note> </trans-unit> <trans-unit id="Encrypted message: unexpected error" xml:space="preserve"> <source>Encrypted message: unexpected error</source> + <target>Şifrelenmiş mesaj: beklenmeyen hata</target> <note>notification</note> </trans-unit> + <trans-unit id="Encryption re-negotiation error" xml:space="preserve"> + <source>Encryption re-negotiation error</source> + <target>Şifreleme yeniden anlaşma hatası</target> + <note>message decrypt error item</note> + </trans-unit> + <trans-unit id="Encryption re-negotiation failed." xml:space="preserve"> + <source>Encryption re-negotiation failed.</source> + <target>Şifreleme yeniden anlaşma başarısız oldu.</target> + <note>No comment provided by engineer.</note> + </trans-unit> <trans-unit id="Enter Passcode" xml:space="preserve"> <source>Enter Passcode</source> + <target>Şifre gir</target> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="Enter correct passphrase." xml:space="preserve"> <source>Enter correct passphrase.</source> + <target>Doğru şifreyi gir.</target> + <note>No comment provided by engineer.</note> + </trans-unit> + <trans-unit id="Enter group name…" xml:space="preserve"> + <source>Enter group name…</source> + <target>Grup adı gir…</target> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="Enter passphrase…" xml:space="preserve"> <source>Enter passphrase…</source> + <target>Parola gir…</target> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="Enter password above to show!" xml:space="preserve"> <source>Enter password above to show!</source> + <target>Göstermek için yukarıdaki şifreyi gir!</target> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="Enter server manually" xml:space="preserve"> <source>Enter server manually</source> + <target>Sunucuya manuel olarak gir</target> + <note>No comment provided by engineer.</note> + </trans-unit> + <trans-unit id="Enter this device name…" xml:space="preserve"> + <source>Enter this device name…</source> + <target>Bu cihazın adını gir…</target> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="Enter welcome message…" xml:space="preserve"> <source>Enter welcome message…</source> + <target>Hoşgeldin mesajı gir…</target> <note>placeholder</note> </trans-unit> <trans-unit id="Enter welcome message… (optional)" xml:space="preserve"> <source>Enter welcome message… (optional)</source> + <target>Hoşgeldin mesajı gir... (opsiyonel)</target> <note>placeholder</note> </trans-unit> + <trans-unit id="Enter your name…" xml:space="preserve"> + <source>Enter your name…</source> + <target>Adını gir…</target> + <note>No comment provided by engineer.</note> + </trans-unit> <trans-unit id="Error" xml:space="preserve"> <source>Error</source> + <target>Hata</target> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="Error aborting address change" xml:space="preserve"> <source>Error aborting address change</source> + <target>Adres değişikliği iptal edilirken hata oluştu</target> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="Error accepting contact request" xml:space="preserve"> <source>Error accepting contact request</source> + <target>Bağlantı isteği kabul edilirken hata oluştu</target> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="Error accessing database file" xml:space="preserve"> <source>Error accessing database file</source> + <target>Veritabanı dosyasına erişilirken hata oluştu</target> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="Error adding member(s)" xml:space="preserve"> <source>Error adding member(s)</source> + <target>Üye(ler) eklenirken hata oluştu</target> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="Error changing address" xml:space="preserve"> <source>Error changing address</source> + <target>Adres değiştirilirken hata oluştu</target> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="Error changing role" xml:space="preserve"> <source>Error changing role</source> + <target>Rol değiştirilirken hata oluştu</target> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="Error changing setting" xml:space="preserve"> <source>Error changing setting</source> + <target>Ayar değiştirilirken hata oluştu</target> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="Error creating address" xml:space="preserve"> <source>Error creating address</source> + <target>Adres oluşturulurken hata oluştu</target> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="Error creating group" xml:space="preserve"> <source>Error creating group</source> + <target>Grup oluşturulurken hata oluştu</target> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="Error creating group link" xml:space="preserve"> <source>Error creating group link</source> + <target>Grup bağlantısı oluşturulurken hata oluştu</target> + <note>No comment provided by engineer.</note> + </trans-unit> + <trans-unit id="Error creating member contact" xml:space="preserve"> + <source>Error creating member contact</source> + <target>Kişi iletişimi oluşturulurken hata oluştu</target> + <note>No comment provided by engineer.</note> + </trans-unit> + <trans-unit id="Error creating message" xml:space="preserve"> + <source>Error creating message</source> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="Error creating profile!" xml:space="preserve"> <source>Error creating profile!</source> + <target>Profil oluşturulurken hata oluştu!</target> + <note>No comment provided by engineer.</note> + </trans-unit> + <trans-unit id="Error decrypting file" xml:space="preserve"> + <source>Error decrypting file</source> + <target>Dosya şifresi çözülürken hata oluştu</target> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="Error deleting chat database" xml:space="preserve"> <source>Error deleting chat database</source> + <target>Sohbet veritabanı silinirken sorun oluştu</target> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="Error deleting chat!" xml:space="preserve"> <source>Error deleting chat!</source> + <target>Sohbet silinirken hata oluştu!</target> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="Error deleting connection" xml:space="preserve"> <source>Error deleting connection</source> + <target>Bağlantı silinirken hata oluştu</target> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="Error deleting contact" xml:space="preserve"> <source>Error deleting contact</source> + <target>Kişi silinirken hata oluştu</target> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="Error deleting database" xml:space="preserve"> <source>Error deleting database</source> + <target>Veritabanı silinirken hata oluştu</target> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="Error deleting old database" xml:space="preserve"> <source>Error deleting old database</source> + <target>Eski veritabanı silinirken hata oluştu</target> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="Error deleting token" xml:space="preserve"> <source>Error deleting token</source> + <target>Token silinirken hata oluştu</target> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="Error deleting user profile" xml:space="preserve"> <source>Error deleting user profile</source> + <target>Kullanıcı profili silinirken hata oluştu</target> + <note>No comment provided by engineer.</note> + </trans-unit> + <trans-unit id="Error enabling delivery receipts!" xml:space="preserve"> + <source>Error enabling delivery receipts!</source> + <target>Görüldü bilgisi etkinleştirilirken hata oluştu!</target> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="Error enabling notifications" xml:space="preserve"> <source>Error enabling notifications</source> + <target>Bildirimler etkinleştirilirken hata oluştu</target> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="Error encrypting database" xml:space="preserve"> <source>Error encrypting database</source> + <target>Veritabanı şifrelemesi çözülürken hata oluştu</target> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="Error exporting chat database" xml:space="preserve"> <source>Error exporting chat database</source> + <target>Sohbet veritabanı dışa aktarılırken hata oluştu</target> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="Error importing chat database" xml:space="preserve"> <source>Error importing chat database</source> + <target>Sohbet veritabanı içe aktarılırken hata oluştu</target> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="Error joining group" xml:space="preserve"> <source>Error joining group</source> + <target>Gruba katılırken hata oluştu</target> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="Error loading %@ servers" xml:space="preserve"> <source>Error loading %@ servers</source> + <target>%@ sunucuları yüklenirken hata oluştu</target> + <note>No comment provided by engineer.</note> + </trans-unit> + <trans-unit id="Error opening chat" xml:space="preserve"> + <source>Error opening chat</source> + <target>Sohbeti açarken sorun oluştu</target> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="Error receiving file" xml:space="preserve"> <source>Error receiving file</source> + <target>Dosya alınırken sorun oluştu</target> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="Error removing member" xml:space="preserve"> <source>Error removing member</source> + <target>Kişiyi silerken sorun oluştu</target> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="Error saving %@ servers" xml:space="preserve"> <source>Error saving %@ servers</source> + <target>%@ sunucuları kaydedilirken sorun oluştu</target> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="Error saving ICE servers" xml:space="preserve"> <source>Error saving ICE servers</source> + <target>ICE sunucularını kaydedirken sorun oluştu</target> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="Error saving group profile" xml:space="preserve"> <source>Error saving group profile</source> + <target>Grup profili kaydedilirken sorun oluştu</target> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="Error saving passcode" xml:space="preserve"> <source>Error saving passcode</source> + <target>Parola kaydedilirken sorun oluştu</target> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="Error saving passphrase to keychain" xml:space="preserve"> <source>Error saving passphrase to keychain</source> + <target>Parolayı Anahtar Zincirine kaydederken hata oluştu</target> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="Error saving user password" xml:space="preserve"> <source>Error saving user password</source> + <target>Kullanıcı şifresi kaydedilirken hata oluştu</target> + <note>No comment provided by engineer.</note> + </trans-unit> + <trans-unit id="Error scanning code: %@" xml:space="preserve"> + <source>Error scanning code: %@</source> + <target>Kod taranırken hata oluştu: %@</target> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="Error sending email" xml:space="preserve"> <source>Error sending email</source> + <target>Eposta gönderilirken hata oluştu</target> + <note>No comment provided by engineer.</note> + </trans-unit> + <trans-unit id="Error sending member contact invitation" xml:space="preserve"> + <source>Error sending member contact invitation</source> + <target>Kişi iletişim daveti gönderilirken hata oluştu</target> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="Error sending message" xml:space="preserve"> <source>Error sending message</source> + <target>Mesaj gönderilirken hata oluştu</target> + <note>No comment provided by engineer.</note> + </trans-unit> + <trans-unit id="Error setting delivery receipts!" xml:space="preserve"> + <source>Error setting delivery receipts!</source> + <target>Görüldü ayarlanırken hata oluştu!</target> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="Error starting chat" xml:space="preserve"> <source>Error starting chat</source> + <target>Sohbet başlatılırken hata oluştu</target> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="Error stopping chat" xml:space="preserve"> <source>Error stopping chat</source> + <target>Sohbet durdurulurken hata oluştu</target> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="Error switching profile!" xml:space="preserve"> <source>Error switching profile!</source> + <target>Profil değiştirilirken hata oluştu!</target> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="Error synchronizing connection" xml:space="preserve"> <source>Error synchronizing connection</source> + <target>Bağlantı senkronizasyonunda hata oluştu</target> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="Error updating group link" xml:space="preserve"> <source>Error updating group link</source> + <target>Grup bağlantısı güncellenirken hata oluştu</target> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="Error updating message" xml:space="preserve"> <source>Error updating message</source> + <target>Mesaj güncellenirken hata oluştu</target> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="Error updating settings" xml:space="preserve"> <source>Error updating settings</source> + <target>Ayarları güncellerken hata oluştu</target> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="Error updating user privacy" xml:space="preserve"> <source>Error updating user privacy</source> + <target>Kullanıcı gizliliği güncellenirken hata oluştu</target> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="Error: " xml:space="preserve"> <source>Error: </source> + <target>Hata: </target> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="Error: %@" xml:space="preserve"> <source>Error: %@</source> + <target>Hata: %@</target> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="Error: URL is invalid" xml:space="preserve"> <source>Error: URL is invalid</source> + <target>Hata: URL geçersiz</target> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="Error: no database file" xml:space="preserve"> <source>Error: no database file</source> + <target>Hata: veritabanı dosyası yok</target> + <note>No comment provided by engineer.</note> + </trans-unit> + <trans-unit id="Even when disabled in the conversation." xml:space="preserve"> + <source>Even when disabled in the conversation.</source> + <target>Konuşma sırasında devre dışı bırakılsa bile.</target> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="Exit without saving" xml:space="preserve"> <source>Exit without saving</source> + <target>Kaydetmeden çık</target> <note>No comment provided by engineer.</note> </trans-unit> + <trans-unit id="Expand" xml:space="preserve"> + <source>Expand</source> + <target>Genişlet</target> + <note>chat item action</note> + </trans-unit> <trans-unit id="Export database" xml:space="preserve"> <source>Export database</source> + <target>Veritabanını dışarı aktar</target> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="Export error:" xml:space="preserve"> <source>Export error:</source> + <target>Dışarı çıkarma hatası:</target> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="Exported database archive." xml:space="preserve"> <source>Exported database archive.</source> - <note>No comment provided by engineer.</note> - </trans-unit> - <trans-unit id="Exporting database archive..." xml:space="preserve"> - <source>Exporting database archive...</source> + <target>Dışarı çıkarılmış veritabanı arşivi.</target> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="Exporting database archive…" xml:space="preserve"> <source>Exporting database archive…</source> + <target>Dışarı çıkarılmış veritabanı arşivi…</target> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="Failed to remove passphrase" xml:space="preserve"> <source>Failed to remove passphrase</source> + <target>Parola kaldırılamadı</target> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="Fast and no wait until the sender is online!" xml:space="preserve"> <source>Fast and no wait until the sender is online!</source> + <target>Hızlı ve gönderici çevrimiçi olana kadar beklemek yok!</target> + <note>No comment provided by engineer.</note> + </trans-unit> + <trans-unit id="Faster joining and more reliable messages." xml:space="preserve"> + <source>Faster joining and more reliable messages.</source> + <target>Daha hızlı katılma ve daha güvenilir mesajlar.</target> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="Favorite" xml:space="preserve"> <source>Favorite</source> + <target>Favori</target> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="File will be deleted from servers." xml:space="preserve"> <source>File will be deleted from servers.</source> + <target>Dosya sunuculardan silinecek.</target> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="File will be received when your contact completes uploading it." xml:space="preserve"> <source>File will be received when your contact completes uploading it.</source> + <target>Dosya kişi yüklemeyi tamamladığında alınacak.</target> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="File will be received when your contact is online, please wait or check later!" xml:space="preserve"> <source>File will be received when your contact is online, please wait or check later!</source> + <target>Dosya kişi çevrimiçi olduğunda alınacaktır, lütfen bekleyin veya daha sonra kontrol edin!</target> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="File: %@" xml:space="preserve"> <source>File: %@</source> + <target>Dosya: %@</target> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="Files & media" xml:space="preserve"> <source>Files & media</source> + <target>Dosyalar & medya</target> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="Files and media" xml:space="preserve"> <source>Files and media</source> + <target>Dosyalar ve medya</target> <note>chat feature</note> </trans-unit> <trans-unit id="Files and media are prohibited in this group." xml:space="preserve"> <source>Files and media are prohibited in this group.</source> + <target>Dosyalar ve medya bu grupta yasaklandı.</target> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="Files and media prohibited!" xml:space="preserve"> <source>Files and media prohibited!</source> + <target>Dosyalar ve medya yasaklandı!</target> + <note>No comment provided by engineer.</note> + </trans-unit> + <trans-unit id="Filter unread and favorite chats." xml:space="preserve"> + <source>Filter unread and favorite chats.</source> + <target>Favori ve okunmamış sohbetleri filtrele.</target> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="Finally, we have them! 🚀" xml:space="preserve"> <source>Finally, we have them! 🚀</source> + <target>Sonunda, onlara sahibiz! 🚀</target> + <note>No comment provided by engineer.</note> + </trans-unit> + <trans-unit id="Find chats faster" xml:space="preserve"> + <source>Find chats faster</source> + <target>Sohbetleri daha hızlı bul</target> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="Fix" xml:space="preserve"> <source>Fix</source> + <target>Düzelt</target> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="Fix connection" xml:space="preserve"> <source>Fix connection</source> + <target>Bağlantıyı düzelt</target> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="Fix connection?" xml:space="preserve"> <source>Fix connection?</source> + <target>Bağlantı düzeltilsin mi?</target> + <note>No comment provided by engineer.</note> + </trans-unit> + <trans-unit id="Fix encryption after restoring backups." xml:space="preserve"> + <source>Fix encryption after restoring backups.</source> + <target>Yedekleri geri yükledikten sonra şifrelemeyi düzelt.</target> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="Fix not supported by contact" xml:space="preserve"> <source>Fix not supported by contact</source> + <target>Düzeltme kişi tarafından desteklenmiyor</target> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="Fix not supported by group member" xml:space="preserve"> <source>Fix not supported by group member</source> + <target>Düzeltme grup üyesi tarafından desteklenmiyor</target> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="For console" xml:space="preserve"> <source>For console</source> + <target>Konsol için</target> + <note>No comment provided by engineer.</note> + </trans-unit> + <trans-unit id="Found desktop" xml:space="preserve"> + <source>Found desktop</source> + <target>Bilgisayar bulundu</target> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="French interface" xml:space="preserve"> <source>French interface</source> + <target>Fransızca arayüz</target> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="Full link" xml:space="preserve"> <source>Full link</source> + <target>Bütün bağlantı adresi</target> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="Full name (optional)" xml:space="preserve"> <source>Full name (optional)</source> + <target>Bütün isim (opsiyonel)</target> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="Full name:" xml:space="preserve"> <source>Full name:</source> + <target>Bütün isim:</target> + <note>No comment provided by engineer.</note> + </trans-unit> + <trans-unit id="Fully decentralized – visible only to members." xml:space="preserve"> + <source>Fully decentralized – visible only to members.</source> + <target>Tamamiyle merkezi olmayan - sadece kişilere görünür.</target> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="Fully re-implemented - work in background!" xml:space="preserve"> <source>Fully re-implemented - work in background!</source> + <target>Arkaplanda çalışma - tamamiyle yeniden yapıldı!</target> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="Further reduced battery usage" xml:space="preserve"> <source>Further reduced battery usage</source> + <target>Daha da azaltılmış pil kullanımı</target> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="GIFs and stickers" xml:space="preserve"> <source>GIFs and stickers</source> + <target>GİFler ve çıkartmalar</target> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="Group" xml:space="preserve"> <source>Group</source> + <target>Grup</target> + <note>No comment provided by engineer.</note> + </trans-unit> + <trans-unit id="Group already exists" xml:space="preserve"> + <source>Group already exists</source> + <target>Grup çoktan mevcut</target> + <note>No comment provided by engineer.</note> + </trans-unit> + <trans-unit id="Group already exists!" xml:space="preserve"> + <source>Group already exists!</source> + <target>Grup çoktan mevcut!</target> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="Group display name" xml:space="preserve"> <source>Group display name</source> + <target>Grup görünen adı</target> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="Group full name (optional)" xml:space="preserve"> <source>Group full name (optional)</source> + <target>Grubun bütün ismi (opsiyonel)</target> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="Group image" xml:space="preserve"> <source>Group image</source> + <target>Grup fotoğrafı</target> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="Group invitation" xml:space="preserve"> <source>Group invitation</source> + <target>Grup daveti</target> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="Group invitation expired" xml:space="preserve"> <source>Group invitation expired</source> + <target>Grup davetinin süresi doldu</target> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="Group invitation is no longer valid, it was removed by sender." xml:space="preserve"> <source>Group invitation is no longer valid, it was removed by sender.</source> + <target>Grup davet artık geçerli değil, gönderici tarafından silindi.</target> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="Group link" xml:space="preserve"> <source>Group link</source> + <target>Grup bağlantısı</target> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="Group links" xml:space="preserve"> <source>Group links</source> + <target>Grup bağlantıları</target> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="Group members can add message reactions." xml:space="preserve"> <source>Group members can add message reactions.</source> + <target>Grup üyeleri mesaj tepkileri ekleyebilir.</target> <note>No comment provided by engineer.</note> </trans-unit> - <trans-unit id="Group members can irreversibly delete sent messages." xml:space="preserve"> - <source>Group members can irreversibly delete sent messages.</source> + <trans-unit id="Group members can irreversibly delete sent messages. (24 hours)" xml:space="preserve"> + <source>Group members can irreversibly delete sent messages. (24 hours)</source> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="Group members can send direct messages." xml:space="preserve"> <source>Group members can send direct messages.</source> + <target>Grup üyeleri doğrudan mesajlar gönderebilir.</target> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="Group members can send disappearing messages." xml:space="preserve"> <source>Group members can send disappearing messages.</source> + <target>Grup üyeleri kaybolan mesajlar gönderebilir.</target> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="Group members can send files and media." xml:space="preserve"> <source>Group members can send files and media.</source> + <target>Grup üyeleri dosyalar ve medya gönderebilir.</target> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="Group members can send voice messages." xml:space="preserve"> <source>Group members can send voice messages.</source> + <target>Grup üyeleri sesli mesajlar gönderebilir.</target> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="Group message:" xml:space="preserve"> <source>Group message:</source> + <target>Grup mesajı:</target> <note>notification</note> </trans-unit> <trans-unit id="Group moderation" xml:space="preserve"> <source>Group moderation</source> + <target>Grup yöneticiliği</target> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="Group preferences" xml:space="preserve"> <source>Group preferences</source> + <target>Grup tercihleri</target> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="Group profile" xml:space="preserve"> <source>Group profile</source> + <target>Grup profili</target> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="Group profile is stored on members' devices, not on the servers." xml:space="preserve"> <source>Group profile is stored on members' devices, not on the servers.</source> + <target>Grup profili üyelerin cihazlarında saklanır, sunucularda değil.</target> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="Group welcome message" xml:space="preserve"> <source>Group welcome message</source> + <target>Grup hoşgeldin mesajı</target> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="Group will be deleted for all members - this cannot be undone!" xml:space="preserve"> <source>Group will be deleted for all members - this cannot be undone!</source> + <target>Grup tüm üyelerden silinecektir - bu geri alınamaz!</target> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="Group will be deleted for you - this cannot be undone!" xml:space="preserve"> <source>Group will be deleted for you - this cannot be undone!</source> + <target>Grup senden silinecektir - bu geri alınamaz!</target> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="Help" xml:space="preserve"> <source>Help</source> + <target>Yardım</target> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="Hidden" xml:space="preserve"> <source>Hidden</source> + <target>Gizlenmiş</target> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="Hidden chat profiles" xml:space="preserve"> <source>Hidden chat profiles</source> + <target>Gizlenmiş sohbet profilleri</target> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="Hidden profile password" xml:space="preserve"> <source>Hidden profile password</source> + <target>Gizlenmiş profil şifresi</target> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="Hide" xml:space="preserve"> <source>Hide</source> + <target>Gizle</target> <note>chat item action</note> </trans-unit> <trans-unit id="Hide app screen in the recent apps." xml:space="preserve"> <source>Hide app screen in the recent apps.</source> + <target>Son uygulamalarda uygulama ekranını gizle.</target> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="Hide profile" xml:space="preserve"> <source>Hide profile</source> + <target>Profili gizle</target> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="Hide:" xml:space="preserve"> <source>Hide:</source> + <target>Gizle:</target> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="History" xml:space="preserve"> <source>History</source> - <note>copied message info</note> + <target>Geçmiş</target> + <note>No comment provided by engineer.</note> + </trans-unit> + <trans-unit id="History is not sent to new members." xml:space="preserve"> + <source>History is not sent to new members.</source> + <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="How SimpleX works" xml:space="preserve"> <source>How SimpleX works</source> + <target>SimpleX nasıl çalışır</target> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="How it works" xml:space="preserve"> <source>How it works</source> + <target>Nasıl çalışıyor</target> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="How to" xml:space="preserve"> <source>How to</source> + <target>Nasıl yapılır</target> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="How to use it" xml:space="preserve"> <source>How to use it</source> + <target>Nasıl kullanılır</target> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="How to use your servers" xml:space="preserve"> <source>How to use your servers</source> + <target>Sunucularını nasıl kullanabilirsin</target> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="ICE servers (one per line)" xml:space="preserve"> <source>ICE servers (one per line)</source> + <target>ICE sunucuları (her satıra bir tane)</target> <note>No comment provided by engineer.</note> </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"> <source>If you can't meet in person, show QR code in a video call, or share the link.</source> - <note>No comment provided by engineer.</note> - </trans-unit> - <trans-unit id="If you cannot meet in person, you can **scan QR code in the video call**, or your contact can share an invitation link." xml:space="preserve"> - <source>If you cannot meet in person, you can **scan QR code in the video call**, or your contact can share an invitation link.</source> + <target>Eğer onunla buluşamıyorsan görüntülü aramada QR kod göster veya bağlantığı paylaş.</target> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="If you enter this passcode when opening the app, all app data will be irreversibly removed!" xml:space="preserve"> <source>If you enter this passcode when opening the app, all app data will be irreversibly removed!</source> + <target>Eğer bu şifreyi uygulamayı açarken girersen, bütün uygulama verileri geri dönülemeyen bir şekilde silinecektir!</target> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="If you enter your self-destruct passcode while opening the app:" xml:space="preserve"> <source>If you enter your self-destruct passcode while opening the app:</source> + <target>Uygulamayı açarken kendi kendini imha eden şifrenizi girerseniz:</target> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="If you need to use the chat now tap **Do it later** below (you will be offered to migrate the database when you restart the app)." xml:space="preserve"> <source>If you need to use the chat now tap **Do it later** below (you will be offered to migrate the database when you restart the app).</source> + <target>Sohbeti şimdi kullanmanız gerekiyorsa aşağıdaki **Daha sonra yap** seçeneğine dokunun (uygulamayı yeniden başlattığınızda veritabanını taşımanız önerilecektir).</target> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="Ignore" xml:space="preserve"> <source>Ignore</source> + <target>Yok say</target> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="Image will be received when your contact completes uploading it." xml:space="preserve"> <source>Image will be received when your contact completes uploading it.</source> + <target>Kişi yüklemeyi bitirdiğinde fotoğraf alınacaktır.</target> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="Image will be received when your contact is online, please wait or check later!" xml:space="preserve"> <source>Image will be received when your contact is online, please wait or check later!</source> + <target>Kişi çevrimiçi olduğunda fotoğraf alınacaktır, lütfen bekleyin veya daha sonra kontrol et!</target> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="Immediately" xml:space="preserve"> <source>Immediately</source> + <target>Hemen</target> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="Immune to spam and abuse" xml:space="preserve"> <source>Immune to spam and abuse</source> + <target>Spam ve kötüye kullanıma karşı bağışıklı</target> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="Import" xml:space="preserve"> <source>Import</source> + <target>İçe aktar</target> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="Import chat database?" xml:space="preserve"> <source>Import chat database?</source> + <target>Sohbet veritabanı içe aktarılsın mı?</target> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="Import database" xml:space="preserve"> <source>Import database</source> + <target>Veritabanını içe aktar</target> + <note>No comment provided by engineer.</note> + </trans-unit> + <trans-unit id="Improved message delivery" xml:space="preserve"> + <source>Improved message delivery</source> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="Improved privacy and security" xml:space="preserve"> <source>Improved privacy and security</source> + <target>Geliştirilmiş gizlilik ve güvenlik</target> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="Improved server configuration" xml:space="preserve"> <source>Improved server configuration</source> + <target>Geliştirilmiş sunucu yapılandırması</target> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="In reply to" xml:space="preserve"> <source>In reply to</source> - <note>copied message info</note> + <target>Cevap olarak</target> + <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="Incognito" xml:space="preserve"> <source>Incognito</source> + <target>Gizli</target> + <note>No comment provided by engineer.</note> + </trans-unit> + <trans-unit id="Incognito groups" xml:space="preserve"> + <source>Incognito groups</source> + <target>Gizli gruplar</target> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="Incognito mode" xml:space="preserve"> <source>Incognito mode</source> + <target>Gizli mod</target> <note>No comment provided by engineer.</note> </trans-unit> - <trans-unit id="Incognito mode is not supported here - your main profile will be sent to group members" xml:space="preserve"> - <source>Incognito mode is not supported here - your main profile will be sent to group members</source> - <note>No comment provided by engineer.</note> - </trans-unit> - <trans-unit id="Incognito mode protects the privacy of your main profile name and image — for each new contact a new random profile is created." xml:space="preserve"> - <source>Incognito mode protects the privacy of your main profile name and image — for each new contact a new random profile is created.</source> + <trans-unit id="Incognito mode protects your privacy by using a new random profile for each contact." xml:space="preserve"> + <source>Incognito mode protects your privacy by using a new random profile for each contact.</source> + <target>Gizli mod her kişiye farklı olarak rasgele profiller kullanarak gizliliğinizi korur.</target> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="Incoming audio call" xml:space="preserve"> <source>Incoming audio call</source> + <target>Gelen sesli arama</target> <note>notification</note> </trans-unit> <trans-unit id="Incoming call" xml:space="preserve"> <source>Incoming call</source> + <target>Gelen arama</target> <note>notification</note> </trans-unit> <trans-unit id="Incoming video call" xml:space="preserve"> <source>Incoming video call</source> + <target>Gelen görüntülü arama</target> <note>notification</note> </trans-unit> <trans-unit id="Incompatible database version" xml:space="preserve"> <source>Incompatible database version</source> + <target>Uyumsuz veritabanı sürümü</target> + <note>No comment provided by engineer.</note> + </trans-unit> + <trans-unit id="Incompatible version" xml:space="preserve"> + <source>Incompatible version</source> + <target>Uyumsuz sürüm</target> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="Incorrect passcode" xml:space="preserve"> <source>Incorrect passcode</source> + <target>Uyumsuz parola</target> <note>PIN entry</note> </trans-unit> <trans-unit id="Incorrect security code!" xml:space="preserve"> <source>Incorrect security code!</source> + <target>Uyumsuz güvenlik kodu!</target> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="Info" xml:space="preserve"> <source>Info</source> + <target>Bilgi</target> <note>chat item action</note> </trans-unit> <trans-unit id="Initial role" xml:space="preserve"> <source>Initial role</source> + <target>Başlangıç rolü</target> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="Install [SimpleX Chat for terminal](https://github.com/simplex-chat/simplex-chat)" xml:space="preserve"> <source>Install [SimpleX Chat for terminal](https://github.com/simplex-chat/simplex-chat)</source> + <target>[Terminal için SimpleX Chat]i indir(https://github.com/simplex-chat/simplex-chat)</target> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="Instant push notifications will be hidden! " xml:space="preserve"> <source>Instant push notifications will be hidden! </source> + <target>Anlık bildirimler gizlenecek! +</target> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="Instantly" xml:space="preserve"> <source>Instantly</source> + <target>Anında</target> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="Interface" xml:space="preserve"> <source>Interface</source> + <target>Arayüz</target> + <note>No comment provided by engineer.</note> + </trans-unit> + <trans-unit id="Invalid QR code" xml:space="preserve"> + <source>Invalid QR code</source> + <target>Geçersiz QR kodu</target> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="Invalid connection link" xml:space="preserve"> <source>Invalid connection link</source> + <target>Geçersiz bağlanma bağlantısı</target> + <note>No comment provided by engineer.</note> + </trans-unit> + <trans-unit id="Invalid display name!" xml:space="preserve"> + <source>Invalid display name!</source> + <note>No comment provided by engineer.</note> + </trans-unit> + <trans-unit id="Invalid link" xml:space="preserve"> + <source>Invalid link</source> + <target>Geçersiz bağlantı</target> + <note>No comment provided by engineer.</note> + </trans-unit> + <trans-unit id="Invalid name!" xml:space="preserve"> + <source>Invalid name!</source> + <target>Geçersiz isim!</target> + <note>No comment provided by engineer.</note> + </trans-unit> + <trans-unit id="Invalid response" xml:space="preserve"> + <source>Invalid response</source> + <target>Geçersiz yanıt</target> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="Invalid server address!" xml:space="preserve"> <source>Invalid server address!</source> + <target>Geçersiz sunucu adresi!</target> <note>No comment provided by engineer.</note> </trans-unit> + <trans-unit id="Invalid status" xml:space="preserve"> + <source>Invalid status</source> + <target>Geçersiz durum</target> + <note>item status text</note> + </trans-unit> <trans-unit id="Invitation expired!" xml:space="preserve"> <source>Invitation expired!</source> + <target>Davetin süresi geçti!</target> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="Invite friends" xml:space="preserve"> <source>Invite friends</source> + <target>Arkadaşları davet et</target> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="Invite members" xml:space="preserve"> <source>Invite members</source> + <target>Üyeleri davet et</target> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="Invite to group" xml:space="preserve"> <source>Invite to group</source> + <target>Gruba davet et</target> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="Irreversible message deletion" xml:space="preserve"> <source>Irreversible message deletion</source> + <target>Geri dönülemeyen mesaj silimi</target> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="Irreversible message deletion is prohibited in this chat." xml:space="preserve"> <source>Irreversible message deletion is prohibited in this chat.</source> + <target>Bu sohbette geri döndürülemez mesaj silme yasaktır.</target> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="Irreversible message deletion is prohibited in this group." xml:space="preserve"> <source>Irreversible message deletion is prohibited in this group.</source> + <target>Bu grupta geri döndürülemez mesaj silme yasaktır.</target> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="It allows having many anonymous connections without any shared data between them in a single chat profile." xml:space="preserve"> <source>It allows having many anonymous connections without any shared data between them in a single chat profile.</source> + <target>Tek bir sohbet profilinde aralarında herhangi bir veri paylaşımı olmadan birçok anonim bağlantıya sahip olmaya izin verir.</target> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="It can happen when you or your connection used the old database backup." xml:space="preserve"> <source>It can happen when you or your connection used the old database backup.</source> + <target>Siz veya bağlantınız eski veritabanı yedeğini kullandığında bu durum ortaya çıkabilir.</target> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="It can happen when: 1. The messages expired in the sending client after 2 days or on the server after 30 days. 2. Message decryption failed, because you or your contact used old database backup. 3. The connection was compromised." xml:space="preserve"> @@ -2169,2775 +3112,3947 @@ 1. The messages expired in the sending client after 2 days or on the server after 30 days. 2. Message decryption failed, because you or your contact used old database backup. 3. The connection was compromised.</source> + <target>Şu durumlarda ortaya çıkabilir: +1. Mesajların gönderici istemcide 2 gün sonra veya sunucuda 30 gün sonra süresi dolmuştur. +2. Siz veya kişi eski veritabanı yedeği kullandığı için mesaj şifre çözme işlemi başarısız olmuştur. +3. Bağlantı tehlikeye girmiştir.</target> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="It seems like you are already connected via this link. If it is not the case, there was an error (%@)." xml:space="preserve"> <source>It seems like you are already connected via this link. If it is not the case, there was an error (%@).</source> + <target>Bu bağlantı üzerinden zaten bağlanmışsınız gibi görünüyor. Eğer durum böyle değilse, bir hata oluştu (%@).</target> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="Italian interface" xml:space="preserve"> <source>Italian interface</source> + <target>İtalyanca arayüz</target> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="Japanese interface" xml:space="preserve"> <source>Japanese interface</source> + <target>Japonca arayüz</target> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="Join" xml:space="preserve"> <source>Join</source> + <target>Katıl</target> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="Join group" xml:space="preserve"> <source>Join group</source> + <target>Gruba katıl</target> + <note>No comment provided by engineer.</note> + </trans-unit> + <trans-unit id="Join group conversations" xml:space="preserve"> + <source>Join group conversations</source> + <note>No comment provided by engineer.</note> + </trans-unit> + <trans-unit id="Join group?" xml:space="preserve"> + <source>Join group?</source> + <target>Gruba katılınsın mı?</target> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="Join incognito" xml:space="preserve"> <source>Join incognito</source> + <target>Gizli katıl</target> + <note>No comment provided by engineer.</note> + </trans-unit> + <trans-unit id="Join with current profile" xml:space="preserve"> + <source>Join with current profile</source> + <target>Şu anki profille katıl</target> + <note>No comment provided by engineer.</note> + </trans-unit> + <trans-unit id="Join your group? This is your link for group %@!" xml:space="preserve"> + <source>Join your group? +This is your link for group %@!</source> + <target>Bu gruba katılınsın mı? +Bu senin grup için bağlantın %@!</target> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="Joining group" xml:space="preserve"> <source>Joining group</source> + <target>Gruba katılınıyor</target> + <note>No comment provided by engineer.</note> + </trans-unit> + <trans-unit id="Keep" xml:space="preserve"> + <source>Keep</source> + <target>Tut</target> + <note>No comment provided by engineer.</note> + </trans-unit> + <trans-unit id="Keep the app open to use it from desktop" xml:space="preserve"> + <source>Keep the app open to use it from desktop</source> + <target>Bilgisayardan kullanmak için uygulamayı açık tut</target> + <note>No comment provided by engineer.</note> + </trans-unit> + <trans-unit id="Keep unused invitation?" xml:space="preserve"> + <source>Keep unused invitation?</source> + <target>Kullanılmamış davet tutulsun mu?</target> + <note>No comment provided by engineer.</note> + </trans-unit> + <trans-unit id="Keep your connections" xml:space="preserve"> + <source>Keep your connections</source> + <target>Bağlantılarınızı koruyun</target> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="KeyChain error" xml:space="preserve"> <source>KeyChain error</source> + <target>Anahtar Zinciri hatası</target> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="Keychain error" xml:space="preserve"> <source>Keychain error</source> + <target>Anahtar Zinciri hatası</target> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="LIVE" xml:space="preserve"> <source>LIVE</source> + <target>CANLI</target> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="Large file!" xml:space="preserve"> <source>Large file!</source> + <target>Büyük dosya!</target> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="Learn more" xml:space="preserve"> <source>Learn more</source> + <target>Daha fazlası</target> <note>No comment provided by engineer.</note> </trans-unit> - <trans-unit id="Leave" xml:space="preserve" approved="no"> + <trans-unit id="Leave" xml:space="preserve"> <source>Leave</source> - <target state="translated">Ayrıl</target> + <target>Ayrıl</target> <note>No comment provided by engineer.</note> </trans-unit> - <trans-unit id="Leave group" xml:space="preserve" approved="no"> + <trans-unit id="Leave group" xml:space="preserve"> <source>Leave group</source> - <target state="translated">Gruptan ayrıl</target> + <target>Gruptan ayrıl</target> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="Leave group?" xml:space="preserve"> <source>Leave group?</source> + <target>Gruptan çıkılsın mı?</target> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="Let's talk in SimpleX Chat" xml:space="preserve"> <source>Let's talk in SimpleX Chat</source> + <target>Hadi SimpleX Chat'te konuşalım</target> <note>email subject</note> </trans-unit> <trans-unit id="Light" xml:space="preserve"> <source>Light</source> + <target>Açık</target> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="Limitations" xml:space="preserve"> <source>Limitations</source> + <target>Sınırlamalar</target> + <note>No comment provided by engineer.</note> + </trans-unit> + <trans-unit id="Link mobile and desktop apps! 🔗" xml:space="preserve"> + <source>Link mobile and desktop apps! 🔗</source> + <target>Telefon ve bilgisayar uygulamalarını bağla! 🔗</target> + <note>No comment provided by engineer.</note> + </trans-unit> + <trans-unit id="Linked desktop options" xml:space="preserve"> + <source>Linked desktop options</source> + <target>Bağlanmış bilgisayar ayarları</target> + <note>No comment provided by engineer.</note> + </trans-unit> + <trans-unit id="Linked desktops" xml:space="preserve"> + <source>Linked desktops</source> + <target>Bağlanmış bilgisayarlar</target> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="Live message!" xml:space="preserve"> <source>Live message!</source> + <target>Canlı mesaj!</target> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="Live messages" xml:space="preserve"> <source>Live messages</source> + <target>Canlı mesajlar</target> + <note>No comment provided by engineer.</note> + </trans-unit> + <trans-unit id="Local" xml:space="preserve"> + <source>Local</source> + <target>Yerel</target> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="Local name" xml:space="preserve"> <source>Local name</source> + <target>Yerel isim</target> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="Local profile data only" xml:space="preserve"> <source>Local profile data only</source> + <target>Sadece yerel profil verisi</target> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="Lock after" xml:space="preserve"> <source>Lock after</source> + <target>Sonra kilitle</target> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="Lock mode" xml:space="preserve"> <source>Lock mode</source> + <target>Kilit modu</target> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="Make a private connection" xml:space="preserve"> <source>Make a private connection</source> + <target>Gizli bir bağlantı oluştur</target> + <note>No comment provided by engineer.</note> + </trans-unit> + <trans-unit id="Make one message disappear" xml:space="preserve"> + <source>Make one message disappear</source> + <target>Bir mesajın kaybolmasını sağlayın</target> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="Make profile private!" xml:space="preserve"> <source>Make profile private!</source> + <target>Profili gizli yap!</target> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="Make sure %@ server addresses are in correct format, line separated and are not duplicated (%@)." xml:space="preserve"> <source>Make sure %@ server addresses are in correct format, line separated and are not duplicated (%@).</source> + <target>%@ sunucu adreslerinin doğru formatta olduğundan, satır ayrımı yapıldığından ve yinelenmediğinden (%@) emin olun.</target> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="Make sure WebRTC ICE server addresses are in correct format, line separated and are not duplicated." xml:space="preserve"> <source>Make sure WebRTC ICE server addresses are in correct format, line separated and are not duplicated.</source> + <target>WebRTC ICE sunucu adreslerinin doğru formatta olduğundan, satırlara ayrıldığından ve yinelenmediğinden emin olun.</target> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="Many people asked: *if SimpleX has no user identifiers, how can it deliver messages?*" xml:space="preserve"> <source>Many people asked: *if SimpleX has no user identifiers, how can it deliver messages?*</source> + <target>Çoğu kişi sordu: *eğer SimpleX'in hiç kullanıcı tanımlayıcıları yok, o zaman mesajları nasıl gönderebiliyor?*</target> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="Mark deleted for everyone" xml:space="preserve"> <source>Mark deleted for everyone</source> + <target>Herkes için silinmiş olarak işaretle</target> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="Mark read" xml:space="preserve"> <source>Mark read</source> + <target>Okunmuş olarak işaretle</target> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="Mark verified" xml:space="preserve"> <source>Mark verified</source> + <target>Onaylanmış olarak işaretle</target> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="Markdown in messages" xml:space="preserve"> <source>Markdown in messages</source> + <target>Mesajlarda işaretleme</target> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="Max 30 seconds, received instantly." xml:space="preserve"> <source>Max 30 seconds, received instantly.</source> + <target>Maksimum 30 saniye, anında alındı.</target> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="Member" xml:space="preserve"> <source>Member</source> + <target>Kişi</target> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="Member role will be changed to "%@". All group members will be notified." xml:space="preserve"> <source>Member role will be changed to "%@". All group members will be notified.</source> + <target>Üye rolü "%@" olarak değiştirilecektir. Ve tüm grup üyeleri bilgilendirilecektir.</target> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="Member role will be changed to "%@". The member will receive a new invitation." xml:space="preserve"> <source>Member role will be changed to "%@". The member will receive a new invitation.</source> + <target>Üye rolü "%@" olarak değiştirilecektir. Ve üye yeni bir davetiye alacaktır.</target> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="Member will be removed from group - this cannot be undone!" xml:space="preserve"> <source>Member will be removed from group - this cannot be undone!</source> + <target>Üye gruptan çıkarılacaktır - bu geri alınamaz!</target> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="Message delivery error" xml:space="preserve"> <source>Message delivery error</source> + <target>Mesaj gönderim hatası</target> + <note>item status text</note> + </trans-unit> + <trans-unit id="Message delivery receipts!" xml:space="preserve"> + <source>Message delivery receipts!</source> + <target>Mesaj alındı bilgisi!</target> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="Message draft" xml:space="preserve"> <source>Message draft</source> + <target>Mesaj taslağı</target> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="Message reactions" xml:space="preserve"> <source>Message reactions</source> + <target>Mesaj tepkileri</target> <note>chat feature</note> </trans-unit> <trans-unit id="Message reactions are prohibited in this chat." xml:space="preserve"> <source>Message reactions are prohibited in this chat.</source> + <target>Mesaj tepkileri bu sohbette yasaklandı.</target> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="Message reactions are prohibited in this group." xml:space="preserve"> <source>Message reactions are prohibited in this group.</source> + <target>Mesaj tepkileri bu grupta yasaklandı.</target> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="Message text" xml:space="preserve"> <source>Message text</source> + <target>Mesaj yazısı</target> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="Messages" xml:space="preserve"> <source>Messages</source> + <target>Mesajlar</target> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="Messages & files" xml:space="preserve"> <source>Messages & files</source> + <target>Mesajlar & dosyalar</target> <note>No comment provided by engineer.</note> </trans-unit> - <trans-unit id="Migrating database archive..." xml:space="preserve"> - <source>Migrating database archive...</source> + <trans-unit id="Messages from %@ will be shown!" xml:space="preserve"> + <source>Messages from %@ will be shown!</source> + <target>%@ den gelen mesajlar gösterilecektir!</target> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="Migrating database archive…" xml:space="preserve"> <source>Migrating database archive…</source> + <target>Veritabanı arşivine geçiliyor…</target> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="Migration error:" xml:space="preserve"> <source>Migration error:</source> + <target>Geçiş hatası:</target> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="Migration failed. Tap **Skip** below to continue using the current database. Please report the issue to the app developers via chat or email [chat@simplex.chat](mailto:chat@simplex.chat)." xml:space="preserve"> <source>Migration failed. Tap **Skip** below to continue using the current database. Please report the issue to the app developers via chat or email [chat@simplex.chat](mailto:chat@simplex.chat).</source> + <target>Geçiş başarısız oldu. Alttaki **Geç** tuşuna basarak şu anki veritabanını kullanabilirsiniz. Lütfen sorunu sohbet veya e-posta yoluyla uygulama geliştiricilerine bildirin[chat@simplex.chat](mailto:chat@simplex.chat).</target> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="Migration is completed" xml:space="preserve"> <source>Migration is completed</source> + <target>Geçiş tamamlandı</target> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="Migrations: %@" xml:space="preserve"> <source>Migrations: %@</source> + <target>Geçişler: %@</target> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="Moderate" xml:space="preserve"> <source>Moderate</source> + <target>Yönet</target> <note>chat item action</note> </trans-unit> <trans-unit id="Moderated at" xml:space="preserve"> <source>Moderated at</source> + <target>de yönetildi</target> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="Moderated at: %@" xml:space="preserve"> <source>Moderated at: %@</source> + <target>%@ de yönetildi</target> <note>copied message info</note> </trans-unit> <trans-unit id="More improvements are coming soon!" xml:space="preserve"> <source>More improvements are coming soon!</source> + <target>Daha fazla geliştirmeler yakında geliyor!</target> <note>No comment provided by engineer.</note> </trans-unit> + <trans-unit id="Most likely this connection is deleted." xml:space="preserve"> + <source>Most likely this connection is deleted.</source> + <target>Büyük ihtimalle bu bağlantı silinmiş.</target> + <note>item status description</note> + </trans-unit> <trans-unit id="Most likely this contact has deleted the connection with you." xml:space="preserve"> <source>Most likely this contact has deleted the connection with you.</source> + <target>Büyük ihtimalle bu kişi seninle bağlantını sildi.</target> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="Multiple chat profiles" xml:space="preserve"> <source>Multiple chat profiles</source> + <target>Çoklu sohbet profili</target> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="Mute" xml:space="preserve"> <source>Mute</source> + <target>Sustur</target> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="Muted when inactive!" xml:space="preserve"> <source>Muted when inactive!</source> + <target>Aktif değilken susturuldu!</target> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="Name" xml:space="preserve"> <source>Name</source> + <target>İsim</target> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="Network & servers" xml:space="preserve"> <source>Network & servers</source> + <target>Ağ & sunucular</target> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="Network settings" xml:space="preserve"> <source>Network settings</source> + <target>Ağ ayarları</target> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="Network status" xml:space="preserve"> <source>Network status</source> + <target>Ağ durumu</target> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="New Passcode" xml:space="preserve"> <source>New Passcode</source> + <target>Yeni şifre</target> + <note>No comment provided by engineer.</note> + </trans-unit> + <trans-unit id="New chat" xml:space="preserve"> + <source>New chat</source> + <target>Yeni sohbet</target> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="New contact request" xml:space="preserve"> <source>New contact request</source> + <target>Yeni bağlantı isteği</target> <note>notification</note> </trans-unit> <trans-unit id="New contact:" xml:space="preserve"> <source>New contact:</source> + <target>Yeni kişi:</target> <note>notification</note> </trans-unit> <trans-unit id="New database archive" xml:space="preserve"> <source>New database archive</source> + <target>Yeni veritabanı arşivi</target> + <note>No comment provided by engineer.</note> + </trans-unit> + <trans-unit id="New desktop app!" xml:space="preserve"> + <source>New desktop app!</source> + <target>Yeni bilgisayar uygulaması!</target> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="New display name" xml:space="preserve"> <source>New display name</source> + <target>Yeni görünen ad</target> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="New in %@" xml:space="preserve"> <source>New in %@</source> + <target>%@ da yeni</target> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="New member role" xml:space="preserve"> <source>New member role</source> + <target>Yeni üye rolü</target> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="New message" xml:space="preserve"> <source>New message</source> + <target>Yeni mesaj</target> <note>notification</note> </trans-unit> <trans-unit id="New passphrase…" xml:space="preserve"> <source>New passphrase…</source> + <target>Yeni parola…</target> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="No" xml:space="preserve"> <source>No</source> + <target>Hayır</target> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="No app password" xml:space="preserve"> <source>No app password</source> + <target>Uygulama şifresi yok</target> <note>Authentication unavailable</note> </trans-unit> <trans-unit id="No contacts selected" xml:space="preserve"> <source>No contacts selected</source> + <target>Hiçbir kişi seçilmedi</target> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="No contacts to add" xml:space="preserve"> <source>No contacts to add</source> + <target>Eklenecek kişi yok</target> + <note>No comment provided by engineer.</note> + </trans-unit> + <trans-unit id="No delivery information" xml:space="preserve"> + <source>No delivery information</source> + <target>Gönderim bilgisi yok</target> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="No device token!" xml:space="preserve"> <source>No device token!</source> + <target>Cihaz tokeni yok!</target> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="No filtered chats" xml:space="preserve"> <source>No filtered chats</source> + <target>Filtrelenmiş sohbetler yok</target> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="No group!" xml:space="preserve"> <source>Group not found!</source> + <target>Grup bulunamadı!</target> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="No history" xml:space="preserve"> <source>No history</source> + <target>Geçmiş yok</target> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="No permission to record voice message" xml:space="preserve"> <source>No permission to record voice message</source> + <target>Sesli mesaj kaydetmek için izin yok</target> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="No received or sent files" xml:space="preserve"> <source>No received or sent files</source> + <target>Hiç alınmış veya gönderilmiş dosya yok</target> + <note>No comment provided by engineer.</note> + </trans-unit> + <trans-unit id="Not compatible!" xml:space="preserve"> + <source>Not compatible!</source> + <target>Uyumlu değil!</target> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="Notifications" xml:space="preserve"> <source>Notifications</source> + <target>Bildirimler</target> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="Notifications are disabled!" xml:space="preserve"> <source>Notifications are disabled!</source> + <target>Bildirimler devre dışı!</target> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="Now admins can: - delete members' messages. - disable members ("observer" role)" xml:space="preserve"> <source>Now admins can: - delete members' messages. - disable members ("observer" role)</source> + <target>Şimdi yöneticiler: +- üyelerin mesajlarını silebilir +- üyeleri devre dışı bırakabilir ("gözlemci" rolü)</target> + <note>No comment provided by engineer.</note> + </trans-unit> + <trans-unit id="OK" xml:space="preserve"> + <source>OK</source> + <target>TAMAM</target> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="Off" xml:space="preserve"> <source>Off</source> - <note>No comment provided by engineer.</note> - </trans-unit> - <trans-unit id="Off (Local)" xml:space="preserve"> - <source>Off (Local)</source> + <target>Kapalı</target> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="Ok" xml:space="preserve"> <source>Ok</source> + <target>Tamam</target> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="Old database" xml:space="preserve"> <source>Old database</source> + <target>Eski veritabanı</target> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="Old database archive" xml:space="preserve"> <source>Old database archive</source> + <target>Eski veritabanı arşivi</target> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="One-time invitation link" xml:space="preserve"> <source>One-time invitation link</source> + <target>Tek zamanlı bağlantı daveti</target> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="Onion hosts will be required for connection. Requires enabling VPN." xml:space="preserve"> <source>Onion hosts will be required for connection. Requires enabling VPN.</source> + <target>Bağlantı için Onion ana bilgisayarları gerekecektir. VPN'nin etkinleştirilmesi gerekir.</target> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="Onion hosts will be used when available. Requires enabling VPN." xml:space="preserve"> <source>Onion hosts will be used when available. Requires enabling VPN.</source> + <target>Onion ana bilgisayarları mevcutsa kullanılacaktır. VPN'nin etkinleştirilmesi gerekir.</target> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="Onion hosts will not be used." xml:space="preserve"> <source>Onion hosts will not be used.</source> + <target>Onion ana bilgisayarları kullanılmayacaktır.</target> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="Only client devices store user profiles, contacts, groups, and messages sent with **2-layer end-to-end encryption**." xml:space="preserve"> <source>Only client devices store user profiles, contacts, groups, and messages sent with **2-layer end-to-end encryption**.</source> + <target>Yalnızca istemci cihazlar kullanıcı profillerini, kişileri, grupları ve **2 katmanlı uçtan uca şifreleme** ile gönderilen mesajları depolar.</target> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="Only group owners can change group preferences." xml:space="preserve"> <source>Only group owners can change group preferences.</source> + <target>Grup tercihlerini yalnızca grup sahipleri değiştirebilir.</target> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="Only group owners can enable files and media." xml:space="preserve"> <source>Only group owners can enable files and media.</source> + <target>Yalnızca grup sahipleri dosyaları ve medyayı etkinleştirebilir.</target> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="Only group owners can enable voice messages." xml:space="preserve"> <source>Only group owners can enable voice messages.</source> + <target>Yalnızca grup sahipleri sesli mesajları etkinleştirebilir.</target> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="Only you can add message reactions." xml:space="preserve"> <source>Only you can add message reactions.</source> + <target>Sadece siz mesaj tepkileri ekleyebilirsiniz.</target> <note>No comment provided by engineer.</note> </trans-unit> - <trans-unit id="Only you can irreversibly delete messages (your contact can mark them for deletion)." xml:space="preserve"> - <source>Only you can irreversibly delete messages (your contact can mark them for deletion).</source> + <trans-unit id="Only you can irreversibly delete messages (your contact can mark them for deletion). (24 hours)" xml:space="preserve"> + <source>Only you can irreversibly delete messages (your contact can mark them for deletion). (24 hours)</source> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="Only you can make calls." xml:space="preserve"> <source>Only you can make calls.</source> + <target>Sadece sen aramalar yapabilirsin.</target> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="Only you can send disappearing messages." xml:space="preserve"> <source>Only you can send disappearing messages.</source> + <target>Sadece sen kaybolan mesajlar gönderebilirsin.</target> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="Only you can send voice messages." xml:space="preserve"> <source>Only you can send voice messages.</source> + <target>Sadece sen sesli mesajlar gönderebilirsin.</target> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="Only your contact can add message reactions." xml:space="preserve"> <source>Only your contact can add message reactions.</source> + <target>Sadece karşıdaki kişi mesaj tepkileri ekleyebilir.</target> <note>No comment provided by engineer.</note> </trans-unit> - <trans-unit id="Only your contact can irreversibly delete messages (you can mark them for deletion)." xml:space="preserve"> - <source>Only your contact can irreversibly delete messages (you can mark them for deletion).</source> + <trans-unit id="Only your contact can irreversibly delete messages (you can mark them for deletion). (24 hours)" xml:space="preserve"> + <source>Only your contact can irreversibly delete messages (you can mark them for deletion). (24 hours)</source> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="Only your contact can make calls." xml:space="preserve"> <source>Only your contact can make calls.</source> + <target>Sadece karşıdaki kişi aramalar yapabilir.</target> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="Only your contact can send disappearing messages." xml:space="preserve"> <source>Only your contact can send disappearing messages.</source> + <target>Sadece karşıdaki kişi kaybolan mesajlar gönderebilir.</target> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="Only your contact can send voice messages." xml:space="preserve"> <source>Only your contact can send voice messages.</source> + <target>Sadece karşıdaki kişi sesli mesajlar gönderebilir.</target> + <note>No comment provided by engineer.</note> + </trans-unit> + <trans-unit id="Open" xml:space="preserve"> + <source>Open</source> + <target>Aç</target> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="Open Settings" xml:space="preserve"> <source>Open Settings</source> + <target>Ayarları aç</target> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="Open chat" xml:space="preserve"> <source>Open chat</source> + <target>Sohbeti aç</target> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="Open chat console" xml:space="preserve"> <source>Open chat console</source> + <target>Sohbet konsolunu aç</target> <note>authentication reason</note> </trans-unit> + <trans-unit id="Open group" xml:space="preserve"> + <source>Open group</source> + <target>Grubu aç</target> + <note>No comment provided by engineer.</note> + </trans-unit> <trans-unit id="Open user profiles" xml:space="preserve"> <source>Open user profiles</source> + <target>Kullanıcı profillerini aç</target> <note>authentication reason</note> </trans-unit> <trans-unit id="Open-source protocol and code – anybody can run the servers." xml:space="preserve"> <source>Open-source protocol and code – anybody can run the servers.</source> + <target>Açık kaynak protokolü ve kodu - herhangi biri sunucuları çalıştırabilir.</target> <note>No comment provided by engineer.</note> </trans-unit> - <trans-unit id="Opening database…" xml:space="preserve"> - <source>Opening database…</source> + <trans-unit id="Opening app…" xml:space="preserve"> + <source>Opening app…</source> + <target>Uygulama açılıyor…</target> <note>No comment provided by engineer.</note> </trans-unit> - <trans-unit id="Opening the link in the browser may reduce connection privacy and security. Untrusted SimpleX links will be red." xml:space="preserve"> - <source>Opening the link in the browser may reduce connection privacy and security. Untrusted SimpleX links will be red.</source> + <trans-unit id="Or scan QR code" xml:space="preserve"> + <source>Or scan QR code</source> + <target>Veya QR kodu okut</target> + <note>No comment provided by engineer.</note> + </trans-unit> + <trans-unit id="Or show this code" xml:space="preserve"> + <source>Or show this code</source> + <target>Veya bu kodu göster</target> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="PING count" xml:space="preserve"> <source>PING count</source> + <target>PING sayısı</target> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="PING interval" xml:space="preserve"> <source>PING interval</source> + <target>PING aralığı</target> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="Passcode" xml:space="preserve"> <source>Passcode</source> + <target>Şifre</target> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="Passcode changed!" xml:space="preserve"> <source>Passcode changed!</source> + <target>Şifre değiştirildi!</target> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="Passcode entry" xml:space="preserve"> <source>Passcode entry</source> + <target>Şifre girişi</target> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="Passcode not changed!" xml:space="preserve"> <source>Passcode not changed!</source> + <target>Şifre değiştirilmedi!</target> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="Passcode set!" xml:space="preserve"> <source>Passcode set!</source> + <target>Şifre ayarlandı!</target> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="Password to show" xml:space="preserve"> <source>Password to show</source> + <target>Gösterilecek şifre</target> <note>No comment provided by engineer.</note> </trans-unit> - <trans-unit id="Paste" xml:space="preserve"> - <source>Paste</source> + <trans-unit id="Past member %@" xml:space="preserve"> + <source>Past member %@</source> + <note>past/unknown group member</note> + </trans-unit> + <trans-unit id="Paste desktop address" xml:space="preserve"> + <source>Paste desktop address</source> + <target>Bilgisayar adresini yapıştır</target> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="Paste image" xml:space="preserve"> <source>Paste image</source> + <target>Fotoğraf yapıştır</target> <note>No comment provided by engineer.</note> </trans-unit> - <trans-unit id="Paste received link" xml:space="preserve"> - <source>Paste received link</source> + <trans-unit id="Paste link to connect!" xml:space="preserve"> + <source>Paste link to connect!</source> <note>No comment provided by engineer.</note> </trans-unit> - <trans-unit id="Paste the link you received into the box below to connect with your contact." xml:space="preserve"> - <source>Paste the link you received into the box below to connect with your contact.</source> + <trans-unit id="Paste the link you received" xml:space="preserve"> + <source>Paste the link you received</source> + <target>Aldığın bağlantıyı yapıştır</target> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="People can connect to you only via the links you share." xml:space="preserve"> <source>People can connect to you only via the links you share.</source> + <target>İnsanlar size yalnızca paylaştığınız bağlantılar üzerinden ulaşabilir.</target> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="Periodically" xml:space="preserve"> <source>Periodically</source> + <target>Periyodik olarak</target> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="Permanent decryption error" xml:space="preserve"> <source>Permanent decryption error</source> + <target>Kalıcı şifre çözümü hatası</target> <note>message decrypt error item</note> </trans-unit> <trans-unit id="Please ask your contact to enable sending voice messages." xml:space="preserve"> <source>Please ask your contact to enable sending voice messages.</source> + <target>Lütfen konuştuğunuz kişiden sesli mesaj göndermeyi etkinleştirmesini isteyin.</target> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="Please check that you used the correct link or ask your contact to send you another one." xml:space="preserve"> <source>Please check that you used the correct link or ask your contact to send you another one.</source> + <target>Lütfen doğru bağlantıyı kullandığınızı kontrol edin veya kişiden size başka bir bağlantı göndermesini isteyin.</target> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="Please check your network connection with %@ and try again." xml:space="preserve"> <source>Please check your network connection with %@ and try again.</source> + <target>Lütfen ağ bağlantınızı %@ ile kontrol edin ve tekrar deneyin.</target> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="Please check yours and your contact preferences." xml:space="preserve"> <source>Please check yours and your contact preferences.</source> + <target>Lütfen sizinkini ve iletişim tercihlerinizi kontrol edin.</target> + <note>No comment provided by engineer.</note> + </trans-unit> + <trans-unit id="Please contact developers. Error: %@" xml:space="preserve"> + <source>Please contact developers. +Error: %@</source> + <target>Lütfen geliştiricilerle irtibata geçin. +Hata: %@</target> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="Please contact group admin." xml:space="preserve"> <source>Please contact group admin.</source> + <target>Lütfen grup yöneticisiyle irtibata geçin.</target> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="Please enter correct current passphrase." xml:space="preserve"> <source>Please enter correct current passphrase.</source> + <target>Lütfen şu anki doğru olan parolayı girin.</target> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="Please enter the previous password after restoring database backup. This action can not be undone." xml:space="preserve"> <source>Please enter the previous password after restoring database backup. This action can not be undone.</source> + <target>Veritabanı yedeğini geri yükledikten sonra lütfen önceki şifreyi girin. Bu işlem geri alınamaz.</target> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="Please remember or store it securely - there is no way to recover a lost passcode!" xml:space="preserve"> <source>Please remember or store it securely - there is no way to recover a lost passcode!</source> + <target>Lütfen iyi hatırlayın veya güvenli bir şekilde saklayın - kaybolmuş bir parolayı kurtarmanın bir yolu yoktur!</target> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="Please report it to the developers." xml:space="preserve"> <source>Please report it to the developers.</source> + <target>Lütfen geliştiricilere bildirin.</target> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="Please restart the app and migrate the database to enable push notifications." xml:space="preserve"> <source>Please restart the app and migrate the database to enable push notifications.</source> + <target>Lütfen uygulamayı yeniden başlatın ve anlık bildirimleri etkinleştirmek için veritabanını taşıyın.</target> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="Please store passphrase securely, you will NOT be able to access chat if you lose it." xml:space="preserve"> <source>Please store passphrase securely, you will NOT be able to access chat if you lose it.</source> + <target>Lütfen parolayı güvenli bir şekilde saklayın, kaybederseniz sohbete ERİŞEMEZSİNİZ.</target> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="Please store passphrase securely, you will NOT be able to change it if you lose it." xml:space="preserve"> <source>Please store passphrase securely, you will NOT be able to change it if you lose it.</source> + <target>Lütfen parolayı güvenli bir şekilde saklayın, kaybederseniz parolayı DEĞİŞTİREMEZSİNİZ.</target> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="Polish interface" xml:space="preserve"> <source>Polish interface</source> + <target>Lehçe arayüz</target> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="Possibly, certificate fingerprint in server address is incorrect" xml:space="preserve"> <source>Possibly, certificate fingerprint in server address is incorrect</source> + <target>Muhtemelen, sunucu adresindeki parmakizi sertifikası doğru değil</target> <note>server test error</note> </trans-unit> <trans-unit id="Preserve the last message draft, with attachments." xml:space="preserve"> <source>Preserve the last message draft, with attachments.</source> + <target>Son mesaj taslağını ekleriyle birlikte koru.</target> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="Preset server" xml:space="preserve"> <source>Preset server</source> + <target>Ön ayarlı sunucu</target> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="Preset server address" xml:space="preserve"> <source>Preset server address</source> + <target>Ön ayarlı sunucu adresi</target> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="Preview" xml:space="preserve"> <source>Preview</source> + <target>Ön izleme</target> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="Privacy & security" xml:space="preserve"> <source>Privacy & security</source> + <target>Gizlilik & güvenlik</target> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="Privacy redefined" xml:space="preserve"> <source>Privacy redefined</source> + <target>Gizlilik yeniden tanımlandı</target> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="Private filenames" xml:space="preserve"> <source>Private filenames</source> + <target>Gizli dosya adları</target> <note>No comment provided by engineer.</note> </trans-unit> + <trans-unit id="Private notes" xml:space="preserve"> + <source>Private notes</source> + <note>name of notes to self</note> + </trans-unit> <trans-unit id="Profile and server connections" xml:space="preserve"> <source>Profile and server connections</source> + <target>Profil ve sunucu bağlantıları</target> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="Profile image" xml:space="preserve"> <source>Profile image</source> + <target>Profil fotoğrafı</target> + <note>No comment provided by engineer.</note> + </trans-unit> + <trans-unit id="Profile name" xml:space="preserve"> + <source>Profile name</source> + <target>Profil ismi</target> + <note>No comment provided by engineer.</note> + </trans-unit> + <trans-unit id="Profile name:" xml:space="preserve"> + <source>Profile name:</source> + <target>Profil ismi:</target> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="Profile password" xml:space="preserve"> <source>Profile password</source> + <target>Profil parolası</target> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="Profile update will be sent to your contacts." xml:space="preserve"> <source>Profile update will be sent to your contacts.</source> + <target>Profil güncellemesi kişilerinize gönderilecektir.</target> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="Prohibit audio/video calls." xml:space="preserve"> <source>Prohibit audio/video calls.</source> + <target>Sesli/görüntülü aramaları yasakla.</target> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="Prohibit irreversible message deletion." xml:space="preserve"> <source>Prohibit irreversible message deletion.</source> + <target>Geri dönüşsüz mesaj silme işlemini yasakla.</target> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="Prohibit message reactions." xml:space="preserve"> <source>Prohibit message reactions.</source> + <target>Mesaj tepkisini yasakla.</target> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="Prohibit messages reactions." xml:space="preserve"> <source>Prohibit messages reactions.</source> + <target>Mesajlarda tepkileri yasakla.</target> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="Prohibit sending direct messages to members." xml:space="preserve"> <source>Prohibit sending direct messages to members.</source> + <target>Geri dönülmez mesaj silme işlemini yasakla.</target> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="Prohibit sending disappearing messages." xml:space="preserve"> <source>Prohibit sending disappearing messages.</source> + <target>Kaybolan mesajların gönderimini yasakla.</target> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="Prohibit sending files and media." xml:space="preserve"> <source>Prohibit sending files and media.</source> + <target>Dosyalar ve medya gönderimlerini yasakla.</target> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="Prohibit sending voice messages." xml:space="preserve"> <source>Prohibit sending voice messages.</source> + <target>Sesli mesajların gönderimini yasakla.</target> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="Protect app screen" xml:space="preserve"> <source>Protect app screen</source> + <target>Uygulama ekranını koru</target> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="Protect your chat profiles with a password!" xml:space="preserve"> <source>Protect your chat profiles with a password!</source> + <target>Bir parolayla birlikte sohbet profillerini koru!</target> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="Protocol timeout" xml:space="preserve"> <source>Protocol timeout</source> + <target>Protokol zaman aşımı</target> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="Protocol timeout per KB" xml:space="preserve"> <source>Protocol timeout per KB</source> + <target>KB başına protokol zaman aşımı</target> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="Push notifications" xml:space="preserve"> <source>Push notifications</source> + <target>Anında bildirimler</target> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="Rate the app" xml:space="preserve"> <source>Rate the app</source> + <target>Uygulamayı değerlendir</target> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="React…" xml:space="preserve"> <source>React…</source> + <target>Tepki ver…</target> <note>chat item menu</note> </trans-unit> <trans-unit id="Read" xml:space="preserve"> <source>Read</source> + <target>Oku</target> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="Read more" xml:space="preserve"> <source>Read more</source> + <target>Dahasını oku</target> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="Read more in [User Guide](https://simplex.chat/docs/guide/app-settings.html#your-simplex-contact-address)." xml:space="preserve"> <source>Read more in [User Guide](https://simplex.chat/docs/guide/app-settings.html#your-simplex-contact-address).</source> + <target>[Kullanıcı Rehberi]nde daha fazlasını okuyun(https://simplex.chat/docs/guide/app-settings.html#your-simplex-contact-address).</target> + <note>No comment provided by engineer.</note> + </trans-unit> + <trans-unit id="Read more in [User Guide](https://simplex.chat/docs/guide/chat-profiles.html#incognito-mode)." xml:space="preserve"> + <source>Read more in [User Guide](https://simplex.chat/docs/guide/chat-profiles.html#incognito-mode).</source> + <target>[Kullanıcı Rehberi]nde daha fazlasını okuyun(https://simplex.chat/docs/guide/chat-profiles.html#incognito-mode).</target> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="Read more in [User Guide](https://simplex.chat/docs/guide/readme.html#connect-to-friends)." xml:space="preserve"> <source>Read more in [User Guide](https://simplex.chat/docs/guide/readme.html#connect-to-friends).</source> + <target>[Kullanıcı Rehberi]nde daha fazlasını okuyun(https://simplex.chat/docs/guide/readme.html#connect-to-friends).</target> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="Read more in our GitHub repository." xml:space="preserve"> <source>Read more in our GitHub repository.</source> + <target>Daha fazlasını GitHub depomuzdan oku.</target> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="Read more in our [GitHub repository](https://github.com/simplex-chat/simplex-chat#readme)." xml:space="preserve"> <source>Read more in our [GitHub repository](https://github.com/simplex-chat/simplex-chat#readme).</source> + <target>[GitHub deposu]nda daha fazlasını okuyun(https://github.com/simplex-chat/simplex-chat#readme).</target> + <note>No comment provided by engineer.</note> + </trans-unit> + <trans-unit id="Receipts are disabled" xml:space="preserve"> + <source>Receipts are disabled</source> + <target>Görüldü devre dışı bırakıldı</target> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="Received at" xml:space="preserve"> <source>Received at</source> + <target>Şuradan alındı</target> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="Received at: %@" xml:space="preserve"> <source>Received at: %@</source> + <target>Şuradan alındı: %@</target> <note>copied message info</note> </trans-unit> <trans-unit id="Received file event" xml:space="preserve"> <source>Received file event</source> + <target>Dosya etkinliği alındı</target> <note>notification</note> </trans-unit> <trans-unit id="Received message" xml:space="preserve"> <source>Received message</source> + <target>Mesaj alındı</target> <note>message info title</note> </trans-unit> <trans-unit id="Receiving address will be changed to a different server. Address change will complete after sender comes online." xml:space="preserve"> <source>Receiving address will be changed to a different server. Address change will complete after sender comes online.</source> + <target>Alıcı adresi farklı bir sunucuya değiştirilecektir. Gönderici çevrimiçi olduktan sonra adres değişikliği tamamlanacaktır.</target> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="Receiving file will be stopped." xml:space="preserve"> <source>Receiving file will be stopped.</source> + <target>Dosya alımı durdurulacaktır.</target> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="Receiving via" xml:space="preserve"> <source>Receiving via</source> + <target>Aracılığıyla alınıyor</target> + <note>No comment provided by engineer.</note> + </trans-unit> + <trans-unit id="Recent history and improved [directory bot](simplex:/contact#/?v=1-4&smp=smp%3A%2F%2Fu2dS9sG8nMNURyZwqASV4yROM28Er0luVTx5X1CsMrU%3D%40smp4.simplex.im%2FeXSPwqTkKyDO3px4fLf1wx3MvPdjdLW3%23%2F%3Fv%3D1-2%26dh%3DMCowBQYDK2VuAyEAaiv6MkMH44L2TcYrt_CsX3ZvM11WgbMEUn0hkIKTOho%253D%26srv%3Do5vmywmrnaxalvz6wi3zicyftgio6psuvyniis6gco6bp6ekl4cqj4id.onion)." xml:space="preserve"> + <source>Recent history and improved [directory bot](simplex:/contact#/?v=1-4&smp=smp%3A%2F%2Fu2dS9sG8nMNURyZwqASV4yROM28Er0luVTx5X1CsMrU%3D%40smp4.simplex.im%2FeXSPwqTkKyDO3px4fLf1wx3MvPdjdLW3%23%2F%3Fv%3D1-2%26dh%3DMCowBQYDK2VuAyEAaiv6MkMH44L2TcYrt_CsX3ZvM11WgbMEUn0hkIKTOho%253D%26srv%3Do5vmywmrnaxalvz6wi3zicyftgio6psuvyniis6gco6bp6ekl4cqj4id.onion).</source> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="Recipients see updates as you type them." xml:space="preserve"> <source>Recipients see updates as you type them.</source> + <target>Alıcılar yazdığına göre güncellemeleri görecektir.</target> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="Reconnect all connected servers to force message delivery. It uses additional traffic." xml:space="preserve"> <source>Reconnect all connected servers to force message delivery. It uses additional traffic.</source> + <target>Mesaj teslimini zorlamak için bağlı tüm sunucuları yeniden bağlayın. Ek trafik kullanır.</target> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="Reconnect servers?" xml:space="preserve"> <source>Reconnect servers?</source> + <target>Sunuculara yeniden bağlanılsın mı?</target> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="Record updated at" xml:space="preserve"> <source>Record updated at</source> + <target>Kayıt şu zamanda güncellendi</target> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="Record updated at: %@" xml:space="preserve"> <source>Record updated at: %@</source> + <target>Kayıt şu zamanda güncellendi: %@</target> <note>copied message info</note> </trans-unit> <trans-unit id="Reduced battery usage" xml:space="preserve"> <source>Reduced battery usage</source> + <target>Azaltılmış pil kullanımı</target> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="Reject" xml:space="preserve"> <source>Reject</source> + <target>Reddet</target> <note>reject incoming call via notification</note> </trans-unit> - <trans-unit id="Reject contact (sender NOT notified)" xml:space="preserve"> - <source>Reject contact (sender NOT notified)</source> + <trans-unit id="Reject (sender NOT notified)" xml:space="preserve"> + <source>Reject (sender NOT notified)</source> + <target>Reddet (göndericiye bildirim GİTMEYECEKTİR)</target> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="Reject contact request" xml:space="preserve"> <source>Reject contact request</source> + <target>Bağlanma isteğini reddet</target> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="Relay server is only used if necessary. Another party can observe your IP address." xml:space="preserve"> <source>Relay server is only used if necessary. Another party can observe your IP address.</source> + <target>Aktarma sunucusu yalnızca gerekli olduğunda kullanılır. Başka bir taraf IP adresinizi gözlemleyebilir.</target> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="Relay server protects your IP address, but it can observe the duration of the call." xml:space="preserve"> <source>Relay server protects your IP address, but it can observe the duration of the call.</source> + <target>Aktarıcı sunucu IP adresinizi korur, ancak aramanın süresini gözlemleyebilir.</target> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="Remove" xml:space="preserve"> <source>Remove</source> + <target>Sil</target> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="Remove member" xml:space="preserve"> <source>Remove member</source> + <target>Kişiyi sil</target> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="Remove member?" xml:space="preserve"> <source>Remove member?</source> + <target>Kişi silinsin mi?</target> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="Remove passphrase from keychain?" xml:space="preserve"> <source>Remove passphrase from keychain?</source> + <target>Anahtar Zinciri'ndeki parola silinsin mi?</target> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="Renegotiate" xml:space="preserve"> <source>Renegotiate</source> + <target>Yeniden müzakere</target> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="Renegotiate encryption" xml:space="preserve"> <source>Renegotiate encryption</source> + <target>Şifrelemeyi yeniden müzakere et</target> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="Renegotiate encryption?" xml:space="preserve"> <source>Renegotiate encryption?</source> + <target>Şifreleme yeniden müzakere edilsin mi?</target> + <note>No comment provided by engineer.</note> + </trans-unit> + <trans-unit id="Repeat connection request?" xml:space="preserve"> + <source>Repeat connection request?</source> + <target>Bağlantı isteği tekrarlansın mı?</target> + <note>No comment provided by engineer.</note> + </trans-unit> + <trans-unit id="Repeat join request?" xml:space="preserve"> + <source>Repeat join request?</source> + <target>Katılma isteği tekrarlansın mı?</target> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="Reply" xml:space="preserve"> <source>Reply</source> + <target>Yanıtla</target> <note>chat item action</note> </trans-unit> <trans-unit id="Required" xml:space="preserve"> <source>Required</source> + <target>Gerekli</target> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="Reset" xml:space="preserve"> <source>Reset</source> + <target>Sıfırla</target> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="Reset colors" xml:space="preserve"> <source>Reset colors</source> + <target>Renkleri sıfırla</target> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="Reset to defaults" xml:space="preserve"> <source>Reset to defaults</source> + <target>Varsayılanlara sıfırla</target> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="Restart the app to create a new chat profile" xml:space="preserve"> <source>Restart the app to create a new chat profile</source> + <target>Yeni bir sohbet profili oluşturmak için uygulamayı yeniden başlatın</target> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="Restart the app to use imported chat database" xml:space="preserve"> <source>Restart the app to use imported chat database</source> + <target>İçe aktarılmış sohbet veritabanını kullanmak için uygulamayı yeniden başlatın</target> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="Restore" xml:space="preserve"> <source>Restore</source> + <target>Geri yükle</target> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="Restore database backup" xml:space="preserve"> <source>Restore database backup</source> + <target>Veritabanı yedeğini geri yükle</target> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="Restore database backup?" xml:space="preserve"> <source>Restore database backup?</source> + <target>Veritabanı yedeği geri yüklensin mi?</target> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="Restore database error" xml:space="preserve"> <source>Restore database error</source> + <target>Veritabanını geri yüklerken hata oluştu</target> + <note>No comment provided by engineer.</note> + </trans-unit> + <trans-unit id="Retry" xml:space="preserve"> + <source>Retry</source> + <target>Yeniden dene</target> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="Reveal" xml:space="preserve"> <source>Reveal</source> + <target>Göster</target> <note>chat item action</note> </trans-unit> <trans-unit id="Revert" xml:space="preserve"> <source>Revert</source> + <target>Geri al</target> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="Revoke" xml:space="preserve"> <source>Revoke</source> + <target>İptal et</target> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="Revoke file" xml:space="preserve"> <source>Revoke file</source> + <target>Dosyayı iptal et</target> <note>cancel file action</note> </trans-unit> <trans-unit id="Revoke file?" xml:space="preserve"> <source>Revoke file?</source> + <target>Dosya iptal edilsin mi?</target> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="Role" xml:space="preserve"> <source>Role</source> + <target>Rol</target> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="Run chat" xml:space="preserve"> <source>Run chat</source> + <target>Sohbeti çalıştır</target> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="SMP servers" xml:space="preserve"> <source>SMP servers</source> + <target>SMP sunucuları</target> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="Save" xml:space="preserve"> <source>Save</source> + <target>Kaydet</target> <note>chat item action</note> </trans-unit> <trans-unit id="Save (and notify contacts)" xml:space="preserve"> <source>Save (and notify contacts)</source> + <target>Kaydet (ve kişilere bildir)</target> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="Save and notify contact" xml:space="preserve"> <source>Save and notify contact</source> + <target>Kaydet ve kişilere bildir</target> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="Save and notify group members" xml:space="preserve"> <source>Save and notify group members</source> + <target>Kaydet ve grup üyelerine bildir</target> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="Save and update group profile" xml:space="preserve"> <source>Save and update group profile</source> + <target>Kaydet ve grup profilini güncelle</target> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="Save archive" xml:space="preserve"> <source>Save archive</source> + <target>Arşivi kaydet</target> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="Save auto-accept settings" xml:space="preserve"> <source>Save auto-accept settings</source> + <target>Otomatik kabul et ayarlarını kaydet</target> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="Save group profile" xml:space="preserve"> <source>Save group profile</source> + <target>Grup profilini kaydet</target> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="Save passphrase and open chat" xml:space="preserve"> <source>Save passphrase and open chat</source> + <target>Parolayı kaydet ve sohbeti aç</target> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="Save passphrase in Keychain" xml:space="preserve"> <source>Save passphrase in Keychain</source> + <target>Parolayı Anahtar Zincirinde kaydet</target> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="Save preferences?" xml:space="preserve"> <source>Save preferences?</source> + <target>Tercihler kaydedilsin mi?</target> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="Save profile password" xml:space="preserve"> <source>Save profile password</source> + <target>Profil şifresini kaydet</target> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="Save servers" xml:space="preserve"> <source>Save servers</source> + <target>Sunucuları kaydet</target> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="Save servers?" xml:space="preserve"> <source>Save servers?</source> + <target>Sunucular kaydedilsin mi?</target> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="Save settings?" xml:space="preserve"> <source>Save settings?</source> + <target>Ayarlar kaydedilsin mi?</target> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="Save welcome message?" xml:space="preserve"> <source>Save welcome message?</source> + <target>Hoşgeldin mesajı kaydedilsin mi?</target> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="Saved WebRTC ICE servers will be removed" xml:space="preserve"> <source>Saved WebRTC ICE servers will be removed</source> + <target>Kaydedilmiş WebRTC ICE sunucuları silinecek</target> <note>No comment provided by engineer.</note> </trans-unit> + <trans-unit id="Saved message" xml:space="preserve"> + <source>Saved message</source> + <note>message info title</note> + </trans-unit> <trans-unit id="Scan QR code" xml:space="preserve"> <source>Scan QR code</source> + <target>QR kodu okut</target> + <note>No comment provided by engineer.</note> + </trans-unit> + <trans-unit id="Scan QR code from desktop" xml:space="preserve"> + <source>Scan QR code from desktop</source> + <target>Bilgisayardan QR kodu okut</target> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="Scan code" xml:space="preserve"> <source>Scan code</source> + <target>Kod okut</target> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="Scan security code from your contact's app." xml:space="preserve"> <source>Scan security code from your contact's app.</source> + <target>Kişinin uygulamasından güvenlik kodunu okut.</target> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="Scan server QR code" xml:space="preserve"> <source>Scan server QR code</source> + <target>Sunucu QR kodu okut</target> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="Search" xml:space="preserve"> <source>Search</source> + <target>Ara</target> + <note>No comment provided by engineer.</note> + </trans-unit> + <trans-unit id="Search bar accepts invitation links." xml:space="preserve"> + <source>Search bar accepts invitation links.</source> + <note>No comment provided by engineer.</note> + </trans-unit> + <trans-unit id="Search or paste SimpleX link" xml:space="preserve"> + <source>Search or paste SimpleX link</source> + <target>Ara veya SimpleX bağlantısını yapıştır</target> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="Secure queue" xml:space="preserve"> <source>Secure queue</source> + <target>Sırayı koru</target> <note>server test step</note> </trans-unit> <trans-unit id="Security assessment" xml:space="preserve"> <source>Security assessment</source> + <target>Güvenlik değerlendirmesi</target> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="Security code" xml:space="preserve"> <source>Security code</source> + <target>Güvenlik kodu</target> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="Select" xml:space="preserve"> <source>Select</source> + <target>Seç</target> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="Self-destruct" xml:space="preserve"> <source>Self-destruct</source> + <target>Kendi kendini imha</target> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="Self-destruct passcode" xml:space="preserve"> <source>Self-destruct passcode</source> + <target>Kendini imha eden şifre</target> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="Self-destruct passcode changed!" xml:space="preserve"> <source>Self-destruct passcode changed!</source> + <target>Kendini imha eden şifre değiştirildi!</target> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="Self-destruct passcode enabled!" xml:space="preserve"> <source>Self-destruct passcode enabled!</source> + <target>Kendini imha eden şifre etkinleştirildi!</target> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="Send" xml:space="preserve"> <source>Send</source> + <target>Gönder</target> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="Send a live message - it will update for the recipient(s) as you type it" xml:space="preserve"> <source>Send a live message - it will update for the recipient(s) as you type it</source> + <target>Bir canlı mesaj gönder - yazışına göre kişiye(lere) kendini günceller</target> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="Send delivery receipts to" xml:space="preserve"> <source>Send delivery receipts to</source> + <target>Görüldü bilgilerini şuraya gönder</target> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="Send direct message" xml:space="preserve"> <source>Send direct message</source> + <target>Doğrudan mesaj gönder</target> + <note>No comment provided by engineer.</note> + </trans-unit> + <trans-unit id="Send direct message to connect" xml:space="preserve"> + <source>Send direct message to connect</source> + <target>Bağlanmak için doğrudan mesaj gönder</target> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="Send disappearing message" xml:space="preserve"> <source>Send disappearing message</source> + <target>Kaybolan bir mesaj gönder</target> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="Send link previews" xml:space="preserve"> <source>Send link previews</source> + <target>Bağlantı ön gösterimleri gönder</target> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="Send live message" xml:space="preserve"> <source>Send live message</source> + <target>Canlı mesaj gönder</target> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="Send notifications" xml:space="preserve"> <source>Send notifications</source> + <target>Bildirimler gönder</target> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="Send notifications:" xml:space="preserve"> <source>Send notifications:</source> + <target>Bildirimler gönder:</target> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="Send questions and ideas" xml:space="preserve"> <source>Send questions and ideas</source> + <target>Fikirler ve sorular gönderin</target> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="Send receipts" xml:space="preserve"> <source>Send receipts</source> + <target>Mesajlar gönder</target> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="Send them from gallery or custom keyboards." xml:space="preserve"> <source>Send them from gallery or custom keyboards.</source> + <target>Bunları galeriden veya özel klavyelerden gönder.</target> + <note>No comment provided by engineer.</note> + </trans-unit> + <trans-unit id="Send up to 100 last messages to new members." xml:space="preserve"> + <source>Send up to 100 last messages to new members.</source> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="Sender cancelled file transfer." xml:space="preserve"> <source>Sender cancelled file transfer.</source> + <target>Gönderici dosya gönderimini iptal etti.</target> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="Sender may have deleted the connection request." xml:space="preserve"> <source>Sender may have deleted the connection request.</source> + <target>Gönderici bağlantı isteğini silmiş olabilir.</target> + <note>No comment provided by engineer.</note> + </trans-unit> + <trans-unit id="Sending delivery receipts will be enabled for all contacts in all visible chat profiles." xml:space="preserve"> + <source>Sending delivery receipts will be enabled for all contacts in all visible chat profiles.</source> + <target>Görüldü bilgisi, tüm görünür sohbet profillerindeki tüm kişiler için etkinleştirilecektir.</target> + <note>No comment provided by engineer.</note> + </trans-unit> + <trans-unit id="Sending delivery receipts will be enabled for all contacts." xml:space="preserve"> + <source>Sending delivery receipts will be enabled for all contacts.</source> + <target>Görüldü bilgisi bütün kişileri için etkinleştirilecektir.</target> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="Sending file will be stopped." xml:space="preserve"> <source>Sending file will be stopped.</source> + <target>Dosya gönderimi durdurulacaktır.</target> + <note>No comment provided by engineer.</note> + </trans-unit> + <trans-unit id="Sending receipts is disabled for %lld contacts" xml:space="preserve"> + <source>Sending receipts is disabled for %lld contacts</source> + <target>Görüldü bilgisi %lld kişileri için devre dışı bırakıldı</target> + <note>No comment provided by engineer.</note> + </trans-unit> + <trans-unit id="Sending receipts is disabled for %lld groups" xml:space="preserve"> + <source>Sending receipts is disabled for %lld groups</source> + <target>Görüldü bilgisi %lld grupları için devre dışı bırakıldı</target> + <note>No comment provided by engineer.</note> + </trans-unit> + <trans-unit id="Sending receipts is enabled for %lld contacts" xml:space="preserve"> + <source>Sending receipts is enabled for %lld contacts</source> + <target>Görüldü bilgisi %lld kişileri için etkinleştirildi</target> + <note>No comment provided by engineer.</note> + </trans-unit> + <trans-unit id="Sending receipts is enabled for %lld groups" xml:space="preserve"> + <source>Sending receipts is enabled for %lld groups</source> + <target>Görüldü bilgisi %lld grupları için etkinleştirildi</target> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="Sending via" xml:space="preserve"> <source>Sending via</source> + <target>Aracılığıyla gönderiliyor</target> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="Sent at" xml:space="preserve"> <source>Sent at</source> + <target>Şuradan gönderildi</target> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="Sent at: %@" xml:space="preserve"> <source>Sent at: %@</source> + <target>Şuradan gönderildi: %@</target> <note>copied message info</note> </trans-unit> <trans-unit id="Sent file event" xml:space="preserve"> <source>Sent file event</source> + <target>Dosya etkinliği gönderildi</target> <note>notification</note> </trans-unit> <trans-unit id="Sent message" xml:space="preserve"> <source>Sent message</source> + <target>Mesaj gönderildi</target> <note>message info title</note> </trans-unit> <trans-unit id="Sent messages will be deleted after set time." xml:space="preserve"> <source>Sent messages will be deleted after set time.</source> + <target>Gönderilen mesajlar ayarlanan süreden sonra silinecektir.</target> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="Server requires authorization to create queues, check password" xml:space="preserve"> <source>Server requires authorization to create queues, check password</source> + <target>Sunucunun sıra oluşturması için yetki gereklidir, şifreyi kontrol edin</target> <note>server test error</note> </trans-unit> <trans-unit id="Server requires authorization to upload, check password" xml:space="preserve"> <source>Server requires authorization to upload, check password</source> + <target>Sunucunun yükleme yapması için yetki gereklidir, şifreyi kontrol edin</target> <note>server test error</note> </trans-unit> <trans-unit id="Server test failed!" xml:space="preserve"> <source>Server test failed!</source> + <target>Sunucu testinde hata oluştu!</target> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="Servers" xml:space="preserve"> <source>Servers</source> + <target>Sunucular</target> + <note>No comment provided by engineer.</note> + </trans-unit> + <trans-unit id="Session code" xml:space="preserve"> + <source>Session code</source> + <target>Oturum kodu</target> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="Set 1 day" xml:space="preserve"> <source>Set 1 day</source> + <target>1 günlüğüne ayarla</target> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="Set contact name…" xml:space="preserve"> <source>Set contact name…</source> + <target>Kişi adı gir…</target> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="Set group preferences" xml:space="preserve"> <source>Set group preferences</source> + <target>Grup tercihlerini ayarla</target> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="Set it instead of system authentication." xml:space="preserve"> <source>Set it instead of system authentication.</source> + <target>Sistem kimlik doğrulaması yerine ayarla.</target> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="Set passcode" xml:space="preserve"> <source>Set passcode</source> + <target>Şifre ayarla</target> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="Set passphrase to export" xml:space="preserve"> <source>Set passphrase to export</source> + <target>Dışa aktarmak için parola ayarla</target> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="Set the message shown to new members!" xml:space="preserve"> <source>Set the message shown to new members!</source> + <target>Yeni üyeler için gösterilen bir mesaj ayarla!</target> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="Set timeouts for proxy/VPN" xml:space="preserve"> <source>Set timeouts for proxy/VPN</source> + <target>Vekil/VPN için zaman aşımları ayarla</target> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="Settings" xml:space="preserve"> <source>Settings</source> + <target>Ayarlar</target> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="Share" xml:space="preserve"> <source>Share</source> + <target>Paylaş</target> <note>chat item action</note> </trans-unit> <trans-unit id="Share 1-time link" xml:space="preserve"> <source>Share 1-time link</source> + <target>Tek kullanımlık bağlantıyı paylaş</target> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="Share address" xml:space="preserve"> <source>Share address</source> + <target>Adresi paylaş</target> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="Share address with contacts?" xml:space="preserve"> <source>Share address with contacts?</source> + <target>Kişilerle adres paylaşılsın mı?</target> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="Share link" xml:space="preserve"> <source>Share link</source> + <target>Bağlantıyı paylaş</target> <note>No comment provided by engineer.</note> </trans-unit> - <trans-unit id="Share one-time invitation link" xml:space="preserve"> - <source>Share one-time invitation link</source> + <trans-unit id="Share this 1-time invite link" xml:space="preserve"> + <source>Share this 1-time invite link</source> + <target>Bu tek kullanımlık bağlantı davetini paylaş</target> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="Share with contacts" xml:space="preserve"> <source>Share with contacts</source> + <target>Kişilerle paylaş</target> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="Show calls in phone history" xml:space="preserve"> <source>Show calls in phone history</source> + <target>Telefon geçmişinde aramaları göster</target> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="Show developer options" xml:space="preserve"> <source>Show developer options</source> + <target>Geliştirici ayarlarını göster</target> + <note>No comment provided by engineer.</note> + </trans-unit> + <trans-unit id="Show last messages" xml:space="preserve"> + <source>Show last messages</source> + <target>Son mesajları göster</target> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="Show preview" xml:space="preserve"> <source>Show preview</source> + <target>Ön gösterimi göser</target> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="Show:" xml:space="preserve"> <source>Show:</source> + <target>Göster:</target> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="SimpleX Address" xml:space="preserve"> <source>SimpleX Address</source> + <target>SimpleX Adresi</target> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="SimpleX Chat security was audited by Trail of Bits." xml:space="preserve"> <source>SimpleX Chat security was audited by Trail of Bits.</source> + <target>SimpleX Chat güvenliği Trails of Bits tarafından denetlenmiştir.</target> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="SimpleX Lock" xml:space="preserve"> <source>SimpleX Lock</source> + <target>SimpleX Kilidi</target> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="SimpleX Lock mode" xml:space="preserve"> <source>SimpleX Lock mode</source> + <target>SimpleX Kilidi modu</target> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="SimpleX Lock not enabled!" xml:space="preserve"> <source>SimpleX Lock not enabled!</source> + <target>SimpleX Kilidi etkinleştirilmedi!</target> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="SimpleX Lock turned on" xml:space="preserve"> <source>SimpleX Lock turned on</source> + <target>SimpleX Kilidi açıldı</target> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="SimpleX address" xml:space="preserve"> <source>SimpleX address</source> + <target>SimpleX adresi</target> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="SimpleX contact address" xml:space="preserve"> <source>SimpleX contact address</source> + <target>SimpleX kişi adresi</target> <note>simplex link type</note> </trans-unit> <trans-unit id="SimpleX encrypted message or connection event" xml:space="preserve"> <source>SimpleX encrypted message or connection event</source> + <target>SimpleX şifrelenmiş mesaj veya bağlantı etkinliği</target> <note>notification</note> </trans-unit> <trans-unit id="SimpleX group link" xml:space="preserve"> <source>SimpleX group link</source> + <target>SimpleX grup bağlantısı</target> <note>simplex link type</note> </trans-unit> <trans-unit id="SimpleX links" xml:space="preserve"> <source>SimpleX links</source> + <target>SimpleX bağlantıları</target> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="SimpleX one-time invitation" xml:space="preserve"> <source>SimpleX one-time invitation</source> + <target>SimpleX tek kullanımlık davet</target> <note>simplex link type</note> </trans-unit> + <trans-unit id="Simplified incognito mode" xml:space="preserve"> + <source>Simplified incognito mode</source> + <target>Basitleştirilmiş gizli mod</target> + <note>No comment provided by engineer.</note> + </trans-unit> <trans-unit id="Skip" xml:space="preserve"> <source>Skip</source> + <target>Atla</target> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="Skipped messages" xml:space="preserve"> <source>Skipped messages</source> + <target>Atlanmış mesajlar</target> <note>No comment provided by engineer.</note> </trans-unit> - <trans-unit id="Small groups (max 10)" xml:space="preserve"> - <source>Small groups (max 10)</source> + <trans-unit id="Small groups (max 20)" xml:space="preserve"> + <source>Small groups (max 20)</source> + <target>Küçük gruplar (en fazla 20 kişi)</target> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="Some non-fatal errors occurred during import - you may see Chat console for more details." xml:space="preserve"> <source>Some non-fatal errors occurred during import - you may see Chat console for more details.</source> + <target>İçe aktarma sırasında bazı ölümcül olmayan hatalar oluştu - daha fazla ayrıntı için Sohbet konsoluna bakabilirsiniz.</target> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="Somebody" xml:space="preserve"> <source>Somebody</source> + <target>Biri</target> <note>notification title</note> </trans-unit> - <trans-unit id="Start a new chat" xml:space="preserve"> - <source>Start a new chat</source> - <note>No comment provided by engineer.</note> - </trans-unit> <trans-unit id="Start chat" xml:space="preserve"> <source>Start chat</source> + <target>Sohbeti başlat</target> + <note>No comment provided by engineer.</note> + </trans-unit> + <trans-unit id="Start chat?" xml:space="preserve"> + <source>Start chat?</source> + <target>Sohbet başlatılsın mı?</target> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="Start migration" xml:space="preserve"> <source>Start migration</source> + <target>Geçişi başlat</target> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="Stop" xml:space="preserve"> <source>Stop</source> + <target>Dur</target> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="Stop SimpleX" xml:space="preserve"> <source>Stop SimpleX</source> + <target>SimpleX'i durdur</target> <note>authentication reason</note> </trans-unit> <trans-unit id="Stop chat to enable database actions" xml:space="preserve"> <source>Stop chat to enable database actions</source> + <target>Veritabanı eylemlerini etkinleştirmek için sohbeti durdur</target> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="Stop chat to export, import or delete chat database. You will not be able to receive and send messages while the chat is stopped." xml:space="preserve"> <source>Stop chat to export, import or delete chat database. You will not be able to receive and send messages while the chat is stopped.</source> + <target>Sohbet veritabanını dışa aktarmak, içe aktarmak veya silmek için sohbeti durdurun. Sohbet durdurulduğunda mesaj alamaz ve gönderemezsiniz.</target> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="Stop chat?" xml:space="preserve"> <source>Stop chat?</source> + <target>Sohbet durdurulsun mu?</target> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="Stop file" xml:space="preserve"> <source>Stop file</source> + <target>Dosyayı durdur</target> <note>cancel file action</note> </trans-unit> <trans-unit id="Stop receiving file?" xml:space="preserve"> <source>Stop receiving file?</source> + <target>Dosya alımı durdurulsun mu?</target> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="Stop sending file?" xml:space="preserve"> <source>Stop sending file?</source> + <target>Dosya gönderimi durdurulsun mu?</target> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="Stop sharing" xml:space="preserve"> <source>Stop sharing</source> + <target>Paylaşmayı durdur</target> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="Stop sharing address?" xml:space="preserve"> <source>Stop sharing address?</source> + <target>Adresi paylaşmak durdurulsun mu?</target> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="Submit" xml:space="preserve"> <source>Submit</source> + <target>Gönder</target> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="Support SimpleX Chat" xml:space="preserve"> <source>Support SimpleX Chat</source> + <target>SimpleX Chat'e destek ol</target> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="System" xml:space="preserve"> <source>System</source> + <target>Sistem</target> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="System authentication" xml:space="preserve"> <source>System authentication</source> + <target>Sistem yetkilendirilmesi</target> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="TCP connection timeout" xml:space="preserve"> <source>TCP connection timeout</source> + <target>TCP bağlantı zaman aşımı</target> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="TCP_KEEPCNT" xml:space="preserve"> <source>TCP_KEEPCNT</source> + <target>TCP_CNTYİTUT</target> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="TCP_KEEPIDLE" xml:space="preserve"> <source>TCP_KEEPIDLE</source> + <target>TCP_BOŞTAKAL</target> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="TCP_KEEPINTVL" xml:space="preserve"> <source>TCP_KEEPINTVL</source> + <target>TCP_TVLDEKAL</target> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="Take picture" xml:space="preserve"> <source>Take picture</source> + <target>Fotoğraf çek</target> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="Tap button " xml:space="preserve"> <source>Tap button </source> + <target>Tuşa bas </target> + <note>No comment provided by engineer.</note> + </trans-unit> + <trans-unit id="Tap to Connect" xml:space="preserve"> + <source>Tap to Connect</source> + <target>Bağlanmak için Tıkla</target> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="Tap to activate profile." xml:space="preserve"> <source>Tap to activate profile.</source> + <target>Profili etkinleştirmek için tıkla.</target> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="Tap to join" xml:space="preserve"> <source>Tap to join</source> + <target>Katılmak için tıkla</target> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="Tap to join incognito" xml:space="preserve"> <source>Tap to join incognito</source> + <target>Gizli katılmak için tıkla</target> + <note>No comment provided by engineer.</note> + </trans-unit> + <trans-unit id="Tap to paste link" xml:space="preserve"> + <source>Tap to paste link</source> + <target>Bağlantıyı yapıştırmak için tıkla</target> + <note>No comment provided by engineer.</note> + </trans-unit> + <trans-unit id="Tap to scan" xml:space="preserve"> + <source>Tap to scan</source> + <target>Taramak için tıkla</target> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="Tap to start a new chat" xml:space="preserve"> <source>Tap to start a new chat</source> + <target>Yeni bir sohbet başlatmak için tıkla</target> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="Test failed at step %@." xml:space="preserve"> <source>Test failed at step %@.</source> + <target>Test %@ adımında başarısız oldu.</target> <note>server test failure</note> </trans-unit> <trans-unit id="Test server" xml:space="preserve"> <source>Test server</source> + <target>Sunucuyu test et</target> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="Test servers" xml:space="preserve"> <source>Test servers</source> + <target>Sunucuları test et</target> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="Tests failed!" xml:space="preserve"> <source>Tests failed!</source> + <target>Testler başarısız oldu!</target> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="Thank you for installing SimpleX Chat!" xml:space="preserve"> <source>Thank you for installing SimpleX Chat!</source> + <target>SimpleX Chat'i indirdiğin için teşekkürler!</target> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="Thanks to the users – [contribute via Weblate](https://github.com/simplex-chat/simplex-chat/tree/stable#help-translating-simplex-chat)!" xml:space="preserve"> <source>Thanks to the users – [contribute via Weblate](https://github.com/simplex-chat/simplex-chat/tree/stable#help-translating-simplex-chat)!</source> + <target>Kullanıcılar için teşekkürler - [Weblate aracılığıyla katkıda bulun](https://github.com/simplex-chat/simplex-chat/tree/stable#help-translating-simplex-chat)!</target> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="Thanks to the users – contribute via Weblate!" xml:space="preserve"> <source>Thanks to the users – contribute via Weblate!</source> + <target>Kullanıcılar için teşekkürler - Weblate aracılığıyla katkıda bulun!</target> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="The 1st platform without any user identifiers – private by design." xml:space="preserve"> <source>The 1st platform without any user identifiers – private by design.</source> + <target>Herhangi bir kullanıcı tanımlayıcısı olmayan ilk platform - tasarım gereği gizli.</target> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="The ID of the next message is incorrect (less or equal to the previous). It can happen because of some bug or when the connection is compromised." xml:space="preserve"> <source>The ID of the next message is incorrect (less or equal to the previous). It can happen because of some bug or when the connection is compromised.</source> + <target>Bir sonraki mesajın kimliği yanlış (bir öncekinden az veya aynı). +Bazı hatalar nedeniyle veya bağlantı tehlikeye girdiğinde meydana gelebilir.</target> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="The app can notify you when you receive messages or contact requests - please open settings to enable." xml:space="preserve"> <source>The app can notify you when you receive messages or contact requests - please open settings to enable.</source> + <target>Uygulama, mesaj veya iletişim isteği aldığınızda sizi bilgilendirebilir - etkinleştirmek için lütfen ayarları açın.</target> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="The attempt to change database passphrase was not completed." xml:space="preserve"> <source>The attempt to change database passphrase was not completed.</source> + <target>Veritabanı parolasını değiştirme girişimi tamamlanmadı.</target> + <note>No comment provided by engineer.</note> + </trans-unit> + <trans-unit id="The code you scanned is not a SimpleX link QR code." xml:space="preserve"> + <source>The code you scanned is not a SimpleX link QR code.</source> + <target>Taradığınız kod bir SimpleX bağlantı QR kodu değildir.</target> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="The connection you accepted will be cancelled!" xml:space="preserve"> <source>The connection you accepted will be cancelled!</source> + <target>Bağlantı kabulünüz iptal edilecektir!</target> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="The contact you shared this link with will NOT be able to connect!" xml:space="preserve"> <source>The contact you shared this link with will NOT be able to connect!</source> + <target>Bu bağlantıyı paylaştığınız kişi BAĞLANAMAYACAKTIR!</target> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="The created archive is available via app Settings / Database / Old database archive." xml:space="preserve"> <source>The created archive is available via app Settings / Database / Old database archive.</source> + <target>Oluşturulan arşive uygulama üzerinden Ayarlar / Veritabanı / Eski veritabanı arşivi üzerinden erişilebilir.</target> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="The encryption is working and the new encryption agreement is not required. It may result in connection errors!" xml:space="preserve"> <source>The encryption is working and the new encryption agreement is not required. It may result in connection errors!</source> - <note>No comment provided by engineer.</note> - </trans-unit> - <trans-unit id="The group is fully decentralized – it is visible only to the members." xml:space="preserve"> - <source>The group is fully decentralized – it is visible only to the members.</source> + <target>Şifreleme çalışıyor ve yeni şifreleme anlaşması gerekli değil. Bağlantı hatalarına neden olabilir!</target> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="The hash of the previous message is different." xml:space="preserve"> <source>The hash of the previous message is different.</source> + <target>Önceki mesajın hash'i farklı.</target> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="The message will be deleted for all members." xml:space="preserve"> <source>The message will be deleted for all members.</source> + <target>Mesaj tüm üyeler için silinecektir.</target> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="The message will be marked as moderated for all members." xml:space="preserve"> <source>The message will be marked as moderated for all members.</source> + <target>Mesaj tüm üyeler için yönetilmiş olarak işaretlenecektir.</target> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="The next generation of private messaging" xml:space="preserve"> <source>The next generation of private messaging</source> + <target>Gizli mesajlaşmanın yeni nesli</target> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="The old database was not removed during the migration, it can be deleted." xml:space="preserve"> <source>The old database was not removed during the migration, it can be deleted.</source> + <target>Eski veritabanı geçiş sırasında kaldırılmadı, silinebilir.</target> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="The profile is only shared with your contacts." xml:space="preserve"> <source>The profile is only shared with your contacts.</source> + <target>Profil sadece kişilerinle paylaşılacak.</target> + <note>No comment provided by engineer.</note> + </trans-unit> + <trans-unit id="The second tick we missed! ✅" xml:space="preserve"> + <source>The second tick we missed! ✅</source> + <target>Özlediğimiz ikinci tik! ✅</target> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="The sender will NOT be notified" xml:space="preserve"> <source>The sender will NOT be notified</source> + <target>Gönderene BİLDİRİLMEYECEKTİR</target> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="The servers for new connections of your current chat profile **%@**." xml:space="preserve"> <source>The servers for new connections of your current chat profile **%@**.</source> + <target>Mevcut sohbet profilinizin yeni bağlantıları için sunucular **%@**.</target> + <note>No comment provided by engineer.</note> + </trans-unit> + <trans-unit id="The text you pasted is not a SimpleX link." xml:space="preserve"> + <source>The text you pasted is not a SimpleX link.</source> + <target>Yapıştırdığın metin bir SimpleX bağlantısı değildir.</target> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="Theme" xml:space="preserve"> <source>Theme</source> - <note>No comment provided by engineer.</note> - </trans-unit> - <trans-unit id="There should be at least one user profile." xml:space="preserve"> - <source>There should be at least one user profile.</source> - <note>No comment provided by engineer.</note> - </trans-unit> - <trans-unit id="There should be at least one visible user profile." xml:space="preserve"> - <source>There should be at least one visible user profile.</source> + <target>Tema</target> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="These settings are for your current profile **%@**." xml:space="preserve"> <source>These settings are for your current profile **%@**.</source> + <target>Bu ayarlar mevcut profiliniz **%@** içindir.</target> <note>No comment provided by engineer.</note> </trans-unit> - <trans-unit id="They can be overridden in contact and group settings" xml:space="preserve"> - <source>They can be overridden in contact and group settings</source> + <trans-unit id="They can be overridden in contact and group settings." xml:space="preserve"> + <source>They can be overridden in contact and group settings.</source> + <target>Bunlar kişi ve grup ayarlarında geçersiz kılınabilir.</target> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="This action cannot be undone - all received and sent files and media will be deleted. Low resolution pictures will remain." xml:space="preserve"> <source>This action cannot be undone - all received and sent files and media will be deleted. Low resolution pictures will remain.</source> + <target>Bu işlem geri alınamaz - alınan ve gönderilen tüm dosyalar ve medya silinecektir. Düşük çözünürlüklü resimler kalacaktır.</target> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="This action cannot be undone - the messages sent and received earlier than selected will be deleted. It may take several minutes." xml:space="preserve"> <source>This action cannot be undone - the messages sent and received earlier than selected will be deleted. It may take several minutes.</source> + <target>Bu işlem geri alınamaz - seçilenden daha önce gönderilen ve alınan mesajlar silinecektir. Bu işlem birkaç dakika sürebilir.</target> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="This action cannot be undone - your profile, contacts, messages and files will be irreversibly lost." xml:space="preserve"> <source>This action cannot be undone - your profile, contacts, messages and files will be irreversibly lost.</source> + <target>Bu işlem geri alınamaz - profiliniz, kişileriniz, mesajlarınız ve dosyalarınız geri döndürülemez şekilde kaybolacaktır.</target> + <note>No comment provided by engineer.</note> + </trans-unit> + <trans-unit id="This device name" xml:space="preserve"> + <source>This device name</source> + <target>Bu cihazın ismi</target> + <note>No comment provided by engineer.</note> + </trans-unit> + <trans-unit id="This display name is invalid. Please choose another name." xml:space="preserve"> + <source>This display name is invalid. Please choose another name.</source> + <note>No comment provided by engineer.</note> + </trans-unit> + <trans-unit id="This group has over %lld members, delivery receipts are not sent." xml:space="preserve"> + <source>This group has over %lld members, delivery receipts are not sent.</source> + <target>Bu grubun %lld den fazla üyesi var,görüldü bilgisi gönderilmedi.</target> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="This group no longer exists." xml:space="preserve"> <source>This group no longer exists.</source> + <target>Bu grup artık mevcut değildir.</target> + <note>No comment provided by engineer.</note> + </trans-unit> + <trans-unit id="This is your own SimpleX address!" xml:space="preserve"> + <source>This is your own SimpleX address!</source> + <target>Bu senin kendi SimpleX adresin!</target> + <note>No comment provided by engineer.</note> + </trans-unit> + <trans-unit id="This is your own one-time link!" xml:space="preserve"> + <source>This is your own one-time link!</source> + <target>Bu senin kendi tek kullanımlık bağlantın!</target> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="This setting applies to messages in your current chat profile **%@**." xml:space="preserve"> <source>This setting applies to messages in your current chat profile **%@**.</source> + <target>Bu ayar, geçerli sohbet profiliniz **%@** deki mesajlara uygulanır.</target> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="To ask any questions and to receive updates:" xml:space="preserve"> <source>To ask any questions and to receive updates:</source> + <target>Soru sormak ve güncellemeleri almak için:</target> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="To connect, your contact can scan QR code or use the link in the app." xml:space="preserve"> <source>To connect, your contact can scan QR code or use the link in the app.</source> + <target>Bağlanmak için, kişi QR kodu okutabilir veya uygulama içinden bağlantıyı kullanabilir.</target> <note>No comment provided by engineer.</note> </trans-unit> - <trans-unit id="To find the profile used for an incognito connection, tap the contact or group name on top of the chat." xml:space="preserve"> - <source>To find the profile used for an incognito connection, tap the contact or group name on top of the chat.</source> + <trans-unit id="To hide unwanted messages." xml:space="preserve"> + <source>To hide unwanted messages.</source> + <target>İstenmeyen mesajları gizlemek için.</target> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="To make a new connection" xml:space="preserve"> <source>To make a new connection</source> + <target>Yeni bir bağlantı oluşturmak için</target> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="To protect privacy, instead of user IDs used by all other platforms, SimpleX has identifiers for message queues, separate for each of your contacts." xml:space="preserve"> <source>To protect privacy, instead of user IDs used by all other platforms, SimpleX has identifiers for message queues, separate for each of your contacts.</source> + <target>Gizliliği korumak için, diğer tüm platformlar gibi kullanıcı kimliği kullanmak yerine, SimpleX mesaj kuyrukları için kişilerinizin her biri için ayrı tanımlayıcılara sahiptir.</target> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="To protect timezone, image/voice files use UTC." xml:space="preserve"> <source>To protect timezone, image/voice files use UTC.</source> + <target>Zaman bölgesini korumak için,fotoğraf/ses dosyaları UTC kullanır.</target> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="To protect your information, turn on SimpleX Lock. You will be prompted to complete authentication before this feature is enabled." xml:space="preserve"> <source>To protect your information, turn on SimpleX Lock. You will be prompted to complete authentication before this feature is enabled.</source> + <target>Bilgilerinizi korumak için SimpleX Lock özelliğini açın. +Bu özellik etkinleştirilmeden önce kimlik doğrulamayı tamamlamanız istenecektir.</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"> <source>To record voice message please grant permission to use Microphone.</source> + <target>Sesli mesaj kaydetmek için lütfen Mikrofon kullanım izni verin.</target> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="To reveal your hidden profile, enter a full password into a search field in **Your chat profiles** page." xml:space="preserve"> <source>To reveal your hidden profile, enter a full password into a search field in **Your chat profiles** page.</source> + <target>Gizli profilinizi ortaya çıkarmak için **Sohbet profilleriniz** sayfasındaki arama alanına tam bir şifre girin.</target> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="To support instant push notifications the chat database has to be migrated." xml:space="preserve"> <source>To support instant push notifications the chat database has to be migrated.</source> + <target>Anlık anlık bildirimleri desteklemek için sohbet veritabanının taşınması gerekir.</target> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="To verify end-to-end encryption with your contact compare (or scan) the code on your devices." xml:space="preserve"> <source>To verify end-to-end encryption with your contact compare (or scan) the code on your devices.</source> + <target>Kişinizle uçtan uca şifrelemeyi doğrulamak için cihazlarınızdaki kodu karşılaştırın (veya tarayın).</target> + <note>No comment provided by engineer.</note> + </trans-unit> + <trans-unit id="Toggle incognito when connecting." xml:space="preserve"> + <source>Toggle incognito when connecting.</source> + <target>Bağlanırken gizli moda geçiş yap.</target> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="Transport isolation" xml:space="preserve"> <source>Transport isolation</source> + <target>Taşıma izolasyonu</target> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="Trying to connect to the server used to receive messages from this contact (error: %@)." xml:space="preserve"> <source>Trying to connect to the server used to receive messages from this contact (error: %@).</source> + <target>Bu kişiden mesaj almak için kullanılan sunucuya bağlanılmaya çalışılıyor (hata: %@).</target> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="Trying to connect to the server used to receive messages from this contact." xml:space="preserve"> <source>Trying to connect to the server used to receive messages from this contact.</source> + <target>Bu kişiden mesaj almak için kullanılan sunucuya bağlanılmaya çalışılıyor.</target> + <note>No comment provided by engineer.</note> + </trans-unit> + <trans-unit id="Turkish interface" xml:space="preserve"> + <source>Turkish interface</source> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="Turn off" xml:space="preserve"> <source>Turn off</source> - <note>No comment provided by engineer.</note> - </trans-unit> - <trans-unit id="Turn off notifications?" xml:space="preserve"> - <source>Turn off notifications?</source> + <target>Kapat</target> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="Turn on" xml:space="preserve"> <source>Turn on</source> + <target>Aç</target> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="Unable to record voice message" xml:space="preserve"> <source>Unable to record voice message</source> + <target>Sesli mesaj kaydedilemedi</target> + <note>No comment provided by engineer.</note> + </trans-unit> + <trans-unit id="Unblock" xml:space="preserve"> + <source>Unblock</source> + <target>Engeli kaldır</target> + <note>No comment provided by engineer.</note> + </trans-unit> + <trans-unit id="Unblock for all" xml:space="preserve"> + <source>Unblock for all</source> + <note>No comment provided by engineer.</note> + </trans-unit> + <trans-unit id="Unblock member" xml:space="preserve"> + <source>Unblock member</source> + <target>Üyenin engelini kaldır</target> + <note>No comment provided by engineer.</note> + </trans-unit> + <trans-unit id="Unblock member for all?" xml:space="preserve"> + <source>Unblock member for all?</source> + <note>No comment provided by engineer.</note> + </trans-unit> + <trans-unit id="Unblock member?" xml:space="preserve"> + <source>Unblock member?</source> + <target>Üyenin engeli kaldırılsın mı?</target> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="Unexpected error: %@" xml:space="preserve"> <source>Unexpected error: %@</source> - <note>No comment provided by engineer.</note> + <target>Beklenmeyen hata: %@</target> + <note>item status description</note> </trans-unit> <trans-unit id="Unexpected migration state" xml:space="preserve"> <source>Unexpected migration state</source> + <target>Beklenmeyen geçiş durumu</target> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="Unfav." xml:space="preserve"> <source>Unfav.</source> + <target>Favorilerden çık.</target> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="Unhide" xml:space="preserve"> <source>Unhide</source> + <target>Gizlemeyi kaldır</target> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="Unhide chat profile" xml:space="preserve"> <source>Unhide chat profile</source> + <target>Sohbet profilinin gizlemesini kaldır</target> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="Unhide profile" xml:space="preserve"> <source>Unhide profile</source> + <target>Proflin gizlenmesini kaldır</target> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="Unit" xml:space="preserve"> <source>Unit</source> + <target>Birim</target> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="Unknown caller" xml:space="preserve"> <source>Unknown caller</source> + <target>Bilinmeyen arayan</target> <note>callkit banner</note> </trans-unit> <trans-unit id="Unknown database error: %@" xml:space="preserve"> <source>Unknown database error: %@</source> + <target>Bilinmeyen veritabanı hatası: %@</target> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="Unknown error" xml:space="preserve"> <source>Unknown error</source> + <target>Bilinmeyen hata</target> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="Unless you use iOS call interface, enable Do Not Disturb mode to avoid interruptions." xml:space="preserve"> <source>Unless you use iOS call interface, enable Do Not Disturb mode to avoid interruptions.</source> + <target>iOS arama arayüzünü kullanmadığınız sürece, kesintileri önlemek için Rahatsız Etmeyin modunu etkinleştirin.</target> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="Unless your contact deleted the connection or this link was already used, it might be a bug - please report it. To connect, please ask your contact to create another connection link and check that you have a stable network connection." xml:space="preserve"> <source>Unless your contact deleted the connection or this link was already used, it might be a bug - please report it. To connect, please ask your contact to create another connection link and check that you have a stable network connection.</source> + <target>Kişiniz bağlantıyı silmediyse veya bu bağlantı kullanılmadıysa, bu bir hata olabilir - lütfen bildirin. +Bağlanmak için lütfen kişinizden başka bir bağlantı oluşturmasını isteyin ve sabit bir ağ bağlantınız olduğunu kontrol edin.</target> + <note>No comment provided by engineer.</note> + </trans-unit> + <trans-unit id="Unlink" xml:space="preserve"> + <source>Unlink</source> + <target>Bağlantıyı Kaldır</target> + <note>No comment provided by engineer.</note> + </trans-unit> + <trans-unit id="Unlink desktop?" xml:space="preserve"> + <source>Unlink desktop?</source> + <target>Bilgisayarla bağlantı kaldırılsın mı?</target> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="Unlock" xml:space="preserve"> <source>Unlock</source> + <target>Kilidi aç</target> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="Unlock app" xml:space="preserve"> <source>Unlock app</source> + <target>Uygulama kilidini aç</target> <note>authentication reason</note> </trans-unit> <trans-unit id="Unmute" xml:space="preserve"> <source>Unmute</source> + <target>Susturmayı kaldır</target> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="Unread" xml:space="preserve"> <source>Unread</source> + <target>Okunmamış</target> + <note>No comment provided by engineer.</note> + </trans-unit> + <trans-unit id="Up to 100 last messages are sent to new members." xml:space="preserve"> + <source>Up to 100 last messages are sent to new members.</source> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="Update" xml:space="preserve"> <source>Update</source> + <target>Güncelle</target> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="Update .onion hosts setting?" xml:space="preserve"> <source>Update .onion hosts setting?</source> + <target>.onion ana bilgisayarların ayarı güncellensin mi?</target> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="Update database passphrase" xml:space="preserve"> <source>Update database passphrase</source> + <target>Veritabanı parolasını güncelle</target> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="Update network settings?" xml:space="preserve"> <source>Update network settings?</source> + <target>Bağlantı ayarları güncellensin mi?</target> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="Update transport isolation mode?" xml:space="preserve"> <source>Update transport isolation mode?</source> + <target>Taşıma izolasyon modu güncellensin mi?</target> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="Updating settings will re-connect the client to all servers." xml:space="preserve"> <source>Updating settings will re-connect the client to all servers.</source> + <target>Ayarların güncellenmesi, istemciyi tüm sunuculara yeniden bağlayacaktır.</target> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="Updating this setting will re-connect the client to all servers." xml:space="preserve"> <source>Updating this setting will re-connect the client to all servers.</source> + <target>Bu ayarın güncellenmesi, istemciyi tüm sunuculara yeniden bağlayacaktır.</target> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="Upgrade and open chat" xml:space="preserve"> <source>Upgrade and open chat</source> + <target>Yükselt ve sohbeti aç</target> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="Upload file" xml:space="preserve"> <source>Upload file</source> + <target>Dosya yükle</target> <note>server test step</note> </trans-unit> <trans-unit id="Use .onion hosts" xml:space="preserve"> <source>Use .onion hosts</source> + <target>.onion ana bilgisayarlarını kullan</target> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="Use SimpleX Chat servers?" xml:space="preserve"> <source>Use SimpleX Chat servers?</source> + <target>SimpleX Chat sunucuları kullanılsın mı?</target> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="Use chat" xml:space="preserve"> <source>Use chat</source> + <target>Sohbeti kullan</target> + <note>No comment provided by engineer.</note> + </trans-unit> + <trans-unit id="Use current profile" xml:space="preserve"> + <source>Use current profile</source> + <target>Şu anki profili kullan</target> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="Use for new connections" xml:space="preserve"> <source>Use for new connections</source> + <target>Yeni bağlantılar için kullan</target> + <note>No comment provided by engineer.</note> + </trans-unit> + <trans-unit id="Use from desktop" xml:space="preserve"> + <source>Use from desktop</source> + <target>Bilgisayardan kullan</target> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="Use iOS call interface" xml:space="preserve"> <source>Use iOS call interface</source> + <target>iOS arama arayüzünden kullan</target> + <note>No comment provided by engineer.</note> + </trans-unit> + <trans-unit id="Use new incognito profile" xml:space="preserve"> + <source>Use new incognito profile</source> + <target>Yeni gizli profilden kullan</target> + <note>No comment provided by engineer.</note> + </trans-unit> + <trans-unit id="Use only local notifications?" xml:space="preserve"> + <source>Use only local notifications?</source> + <target>Sadece yerel bildirimler kullanılsın mı?</target> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="Use server" xml:space="preserve"> <source>Use server</source> + <target>Sunucu kullan</target> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="User profile" xml:space="preserve"> <source>User profile</source> + <target>Kullanıcı profili</target> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="Using .onion hosts requires compatible VPN provider." xml:space="preserve"> <source>Using .onion hosts requires compatible VPN provider.</source> + <target>.onion ana bilgisayarlarını kullanmak için uyumlu VPN sağlayıcısı gerekir.</target> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="Using SimpleX Chat servers." xml:space="preserve"> <source>Using SimpleX Chat servers.</source> + <target>SimpleX Chat sunucuları kullanılıyor.</target> + <note>No comment provided by engineer.</note> + </trans-unit> + <trans-unit id="Verify code with desktop" xml:space="preserve"> + <source>Verify code with desktop</source> + <target>Bilgisayarla kodu doğrula</target> + <note>No comment provided by engineer.</note> + </trans-unit> + <trans-unit id="Verify connection" xml:space="preserve"> + <source>Verify connection</source> + <target>Bağlantıyı doğrula</target> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="Verify connection security" xml:space="preserve"> <source>Verify connection security</source> + <target>Bağlantı güvenliğini doğrula</target> + <note>No comment provided by engineer.</note> + </trans-unit> + <trans-unit id="Verify connections" xml:space="preserve"> + <source>Verify connections</source> + <target>Bağlantıları doğrula</target> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="Verify security code" xml:space="preserve"> <source>Verify security code</source> + <target>Güvenlik kodunu doğrula</target> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="Via browser" xml:space="preserve"> <source>Via browser</source> + <target>Tarayıcı üzerinden</target> + <note>No comment provided by engineer.</note> + </trans-unit> + <trans-unit id="Via secure quantum resistant protocol." xml:space="preserve"> + <source>Via secure quantum resistant protocol.</source> + <target>Güvenli kuantum dirençli protokol ile.</target> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="Video call" xml:space="preserve"> <source>Video call</source> + <target>Görüntülü arama</target> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="Video will be received when your contact completes uploading it." xml:space="preserve"> <source>Video will be received when your contact completes uploading it.</source> + <target>Kişiniz yüklemeyi tamamladığında video alınacaktır.</target> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="Video will be received when your contact is online, please wait or check later!" xml:space="preserve"> <source>Video will be received when your contact is online, please wait or check later!</source> + <target>Kişiniz çevrimiçi olduğunda video alınacaktır, lütfen bekleyin veya daha sonra kontrol edin!</target> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="Videos and files up to 1gb" xml:space="preserve"> <source>Videos and files up to 1gb</source> + <target>1gb'a kadar videolar ve dosyalar</target> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="View security code" xml:space="preserve"> <source>View security code</source> + <target>Güvenlik kodunu görüntüle</target> <note>No comment provided by engineer.</note> </trans-unit> + <trans-unit id="Visible history" xml:space="preserve"> + <source>Visible history</source> + <note>chat feature</note> + </trans-unit> <trans-unit id="Voice messages" xml:space="preserve"> <source>Voice messages</source> + <target>Sesli mesajlar</target> <note>chat feature</note> </trans-unit> <trans-unit id="Voice messages are prohibited in this chat." xml:space="preserve"> <source>Voice messages are prohibited in this chat.</source> + <target>Bu sohbette sesli mesajlar yasaktır.</target> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="Voice messages are prohibited in this group." xml:space="preserve"> <source>Voice messages are prohibited in this group.</source> + <target>Bu grupta sesli mesajlar yasaktır.</target> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="Voice messages prohibited!" xml:space="preserve"> <source>Voice messages prohibited!</source> + <target>Sesli mesajlar yasaktır!</target> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="Voice message…" xml:space="preserve"> <source>Voice message…</source> + <target>Sesli mesaj…</target> + <note>No comment provided by engineer.</note> + </trans-unit> + <trans-unit id="Waiting for desktop..." xml:space="preserve"> + <source>Waiting for desktop...</source> + <target>Bilgisayar için bekleniyor...</target> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="Waiting for file" xml:space="preserve"> <source>Waiting for file</source> + <target>Dosya bekleniyor</target> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="Waiting for image" xml:space="preserve"> <source>Waiting for image</source> + <target>Görsel bekleniyor</target> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="Waiting for video" xml:space="preserve"> <source>Waiting for video</source> + <target>Video bekleniyor</target> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="Warning: you may lose some data!" xml:space="preserve"> <source>Warning: you may lose some data!</source> + <target>Uyarı: Bazı verileri kaybedebilirsin!</target> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="WebRTC ICE servers" xml:space="preserve"> <source>WebRTC ICE servers</source> + <target>WebRTC ICE sunucuları</target> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="Welcome %@!" xml:space="preserve"> <source>Welcome %@!</source> + <target>Hoşgeldin %@!</target> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="Welcome message" xml:space="preserve"> <source>Welcome message</source> + <target>Karşılama mesajı</target> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="What's new" xml:space="preserve"> <source>What's new</source> + <target>Neler yeni</target> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="When available" xml:space="preserve"> <source>When available</source> + <target>Mevcut olduğunda</target> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="When people request to connect, you can accept or reject it." xml:space="preserve"> <source>When people request to connect, you can accept or reject it.</source> + <target>İnsanlar bağlantı talebinde bulunduğunda, kabul edebilir veya reddedebilirsiniz.</target> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="When you share an incognito profile with somebody, this profile will be used for the groups they invite you to." xml:space="preserve"> <source>When you share an incognito profile with somebody, this profile will be used for the groups they invite you to.</source> + <target>Biriyle gizli bir profil paylaştığınızda, bu profil sizi davet ettikleri gruplar için kullanılacaktır.</target> + <note>No comment provided by engineer.</note> + </trans-unit> + <trans-unit id="With encrypted files and media." xml:space="preserve"> + <source>With encrypted files and media.</source> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="With optional welcome message." xml:space="preserve"> <source>With optional welcome message.</source> + <target>İsteğe bağlı karşılama mesajı ile.</target> + <note>No comment provided by engineer.</note> + </trans-unit> + <trans-unit id="With reduced battery usage." xml:space="preserve"> + <source>With reduced battery usage.</source> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="Wrong database passphrase" xml:space="preserve"> <source>Wrong database passphrase</source> + <target>Yanlış veritabanı parolası</target> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="Wrong passphrase!" xml:space="preserve"> <source>Wrong passphrase!</source> + <target>Yanlış parola!</target> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="XFTP servers" xml:space="preserve"> <source>XFTP servers</source> + <target>XFTP sunucuları</target> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="You" xml:space="preserve"> <source>You</source> + <target>Sen</target> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="You accepted connection" xml:space="preserve"> <source>You accepted connection</source> + <target>Bağlantıyı onayladın</target> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="You allow" xml:space="preserve"> <source>You allow</source> + <target>İzin veriyorsunuz</target> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="You already have a chat profile with the same display name. Please choose another name." xml:space="preserve"> <source>You already have a chat profile with the same display name. Please choose another name.</source> + <target>Aynı görünen ada sahip bir konuşma profilin zaten var. Lütfen başka bir ad seç.</target> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="You are already connected to %@." xml:space="preserve"> <source>You are already connected to %@.</source> + <target>Zaten %@'a bağlısınız.</target> + <note>No comment provided by engineer.</note> + </trans-unit> + <trans-unit id="You are already connecting to %@." xml:space="preserve"> + <source>You are already connecting to %@.</source> + <target>Zaten %@'a bağlanıyorsunuz.</target> + <note>No comment provided by engineer.</note> + </trans-unit> + <trans-unit id="You are already connecting via this one-time link!" xml:space="preserve"> + <source>You are already connecting via this one-time link!</source> + <target>Bu tek seferlik bağlantı üzerinden zaten bağlanıyorsunuz!</target> + <note>No comment provided by engineer.</note> + </trans-unit> + <trans-unit id="You are already in group %@." xml:space="preserve"> + <source>You are already in group %@.</source> + <target>Zaten %@ grubundasın.</target> + <note>No comment provided by engineer.</note> + </trans-unit> + <trans-unit id="You are already joining the group %@." xml:space="preserve"> + <source>You are already joining the group %@.</source> + <target>Zaten %@ grubuna katılıyorsunuz.</target> + <note>No comment provided by engineer.</note> + </trans-unit> + <trans-unit id="You are already joining the group via this link!" xml:space="preserve"> + <source>You are already joining the group via this link!</source> + <target>Bu bağlantı üzerinden gruba zaten katılıyorsunuz!</target> + <note>No comment provided by engineer.</note> + </trans-unit> + <trans-unit id="You are already joining the group via this link." xml:space="preserve"> + <source>You are already joining the group via this link.</source> + <target>Gruba zaten bu bağlantı üzerinden katılıyorsunuz.</target> + <note>No comment provided by engineer.</note> + </trans-unit> + <trans-unit id="You are already joining the group! Repeat join request?" xml:space="preserve"> + <source>You are already joining the group! +Repeat join request?</source> + <target>Gruba zaten katılıyorsunuz! +Katılma isteği tekrarlansın mı?</target> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="You are connected to the server used to receive messages from this contact." xml:space="preserve"> <source>You are connected to the server used to receive messages from this contact.</source> + <target>Bu kişiden mesaj almak için kullanılan sunucuya bağlısınız.</target> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="You are invited to group" xml:space="preserve"> <source>You are invited to group</source> + <target>Gruba davet edildiniz</target> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="You can accept calls from lock screen, without device and app authentication." xml:space="preserve"> <source>You can accept calls from lock screen, without device and app authentication.</source> - <note>No comment provided by engineer.</note> - </trans-unit> - <trans-unit id="You can also connect by clicking the link. If it opens in the browser, click **Open in mobile app** button." xml:space="preserve"> - <source>You can also connect by clicking the link. If it opens in the browser, click **Open in mobile app** button.</source> + <target>Cihaz ve uygulama kimlik doğrulaması olmadan kilit ekranından çağrı kabul edebilirsiniz.</target> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="You can create it later" xml:space="preserve"> <source>You can create it later</source> + <target>Daha sonra oluşturabilirsiniz</target> + <note>No comment provided by engineer.</note> + </trans-unit> + <trans-unit id="You can enable later via Settings" xml:space="preserve"> + <source>You can enable later via Settings</source> + <target>Daha sonra Ayarlardan etkinleştirebilirsin</target> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="You can enable them later via app Privacy & Security settings." xml:space="preserve"> <source>You can enable them later via app Privacy & Security settings.</source> + <target>Daha sonra uygulamanın Gizlilik ve Güvenlik ayarlarından etkinleştirebilirsiniz.</target> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="You can hide or mute a user profile - swipe it to the right." xml:space="preserve"> <source>You can hide or mute a user profile - swipe it to the right.</source> + <target>Bir kullanıcı profilini gizleyebilir veya sessize alabilirsiniz - sağa kaydırın.</target> + <note>No comment provided by engineer.</note> + </trans-unit> + <trans-unit id="You can make it visible to your SimpleX contacts via Settings." xml:space="preserve"> + <source>You can make it visible to your SimpleX contacts via Settings.</source> + <target>Ayarlardan SimpleX kişilerinize görünür yapabilirsiniz.</target> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="You can now send messages to %@" xml:space="preserve"> <source>You can now send messages to %@</source> + <target>Artık %@ adresine mesaj gönderebilirsin</target> <note>notification body</note> </trans-unit> <trans-unit id="You can set lock screen notification preview via settings." xml:space="preserve"> <source>You can set lock screen notification preview via settings.</source> + <target>Kilit ekranı bildirim önizlemesini ayarlar üzerinden ayarlayabilirsiniz.</target> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="You can share a link or a QR code - anybody will be able to join the group. You won't lose members of the group if you later delete it." xml:space="preserve"> <source>You can share a link or a QR code - anybody will be able to join the group. You won't lose members of the group if you later delete it.</source> + <target>Bir bağlantı veya QR kodu paylaşabilirsiniz - bu durumda herkes gruba katılabilir. Daha sonra silseniz bile grubun üyelerini kaybetmezsiniz.</target> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="You can share this address with your contacts to let them connect with **%@**." xml:space="preserve"> <source>You can share this address with your contacts to let them connect with **%@**.</source> + <target>Bu adresi kişilerinizle paylaşarak onların **%@** ile bağlantı kurmasını sağlayabilirsiniz.</target> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="You can share your address as a link or QR code - anybody can connect to you." xml:space="preserve"> <source>You can share your address as a link or QR code - anybody can connect to you.</source> + <target>Adresinizi bir bağlantı veya QR kodu olarak paylaşabilirsiniz - herkes size bağlanabilir.</target> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="You can start chat via app Settings / Database or by restarting the app" xml:space="preserve"> <source>You can start chat via app Settings / Database or by restarting the app</source> + <target>Sohbeti uygulamada Ayarlar / Veritabanı üzerinden veya uygulamayı yeniden başlatarak başlatabilirsiniz</target> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="You can turn on SimpleX Lock via Settings." xml:space="preserve"> <source>You can turn on SimpleX Lock via Settings.</source> + <target>SimpleX Kilidini Ayarlar üzerinden açabilirsiniz.</target> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="You can use markdown to format messages:" xml:space="preserve"> <source>You can use markdown to format messages:</source> + <target>Mesajları biçimlendirmek için markdown kullanabilirsiniz:</target> + <note>No comment provided by engineer.</note> + </trans-unit> + <trans-unit id="You can view invitation link again in connection details." xml:space="preserve"> + <source>You can view invitation link again in connection details.</source> + <target>Bağlantı detaylarından davet bağlantısını yeniden görüntüleyebilirsin.</target> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="You can't send messages!" xml:space="preserve"> <source>You can't send messages!</source> + <target>Mesajlar gönderemezsiniz!</target> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="You control through which server(s) **to receive** the messages, your contacts – the servers you use to message them." xml:space="preserve"> <source>You control through which server(s) **to receive** the messages, your contacts – the servers you use to message them.</source> + <target>Mesajların hangi sunucu(lar)dan **alınacağını**, kişilerinizi - onlara mesaj göndermek için kullandığınız sunucuları - siz kontrol edersiniz.</target> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="You could not be verified; please try again." xml:space="preserve"> <source>You could not be verified; please try again.</source> + <target>Doğrulanamadınız; lütfen tekrar deneyin.</target> + <note>No comment provided by engineer.</note> + </trans-unit> + <trans-unit id="You have already requested connection via this address!" xml:space="preserve"> + <source>You have already requested connection via this address!</source> + <target>Bu adres üzerinden zaten bağlantı talebinde bulundunuz!</target> + <note>No comment provided by engineer.</note> + </trans-unit> + <trans-unit id="You have already requested connection! Repeat connection request?" xml:space="preserve"> + <source>You have already requested connection! +Repeat connection request?</source> + <target>Zaten bağlantı isteğinde bulundunuz! +Bağlantı isteği tekrarlansın mı?</target> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="You have no chats" xml:space="preserve"> <source>You have no chats</source> + <target>Hiç sohbetiniz yok</target> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="You have to enter passphrase every time the app starts - it is not stored on the device." xml:space="preserve"> <source>You have to enter passphrase every time the app starts - it is not stored on the device.</source> + <target>Uygulama her başladığında parola girmeniz gerekir - parola cihazınızda saklanmaz.</target> <note>No comment provided by engineer.</note> </trans-unit> - <trans-unit id="You invited your contact" xml:space="preserve"> - <source>You invited your contact</source> + <trans-unit id="You invited a contact" xml:space="preserve"> + <source>You invited a contact</source> + <target>Bir kişiyi davet ettin</target> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="You joined this group" xml:space="preserve"> <source>You joined this group</source> + <target>Bu gruba katıldınız</target> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="You joined this group. Connecting to inviting group member." xml:space="preserve"> <source>You joined this group. Connecting to inviting group member.</source> + <target>Bu gruba katıldınız. Davet eden grup üyesine bağlanılıyor.</target> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="You must use the most recent version of your chat database on one device ONLY, otherwise you may stop receiving the messages from some contacts." xml:space="preserve"> <source>You must use the most recent version of your chat database on one device ONLY, otherwise you may stop receiving the messages from some contacts.</source> + <target>Sohbet veritabanınızın en son sürümünü SADECE bir cihazda kullanmalısınız, aksi takdirde bazı kişilerden daha fazla mesaj alamayabilirsiniz.</target> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="You need to allow your contact to send voice messages to be able to send them." xml:space="preserve"> <source>You need to allow your contact to send voice messages to be able to send them.</source> + <target>Sesli mesaj gönderebilmeniz için kişinizin de sesli mesaj göndermesine izin vermeniz gerekir.</target> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="You rejected group invitation" xml:space="preserve"> <source>You rejected group invitation</source> + <target>Grup davetini reddettiniz.</target> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="You sent group invitation" xml:space="preserve"> <source>You sent group invitation</source> + <target>Grup daveti gönderdiniz</target> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="You will be connected to group when the group host's device is online, please wait or check later!" xml:space="preserve"> <source>You will be connected to group when the group host's device is online, please wait or check later!</source> + <target>Grup sahibinin cihazı çevrimiçi olduğunda gruba bağlanacaksınız, lütfen bekleyin veya daha sonra kontrol edin!</target> + <note>No comment provided by engineer.</note> + </trans-unit> + <trans-unit id="You will be connected when group link host's device is online, please wait or check later!" xml:space="preserve"> + <source>You will be connected when group link host's device is online, please wait or check later!</source> + <target>Grup sahibinin cihazı çevrimiçi olduğunda gruba bağlanacaksınız, lütfen bekleyin veya daha sonra kontrol edin!</target> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="You will be connected when your connection request is accepted, please wait or check later!" xml:space="preserve"> <source>You will be connected when your connection request is accepted, please wait or check later!</source> + <target>Bağlantı isteğiniz kabul edildiğinde bağlanacaksınız, lütfen bekleyin veya daha sonra kontrol edin!</target> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="You will be connected when your contact's device is online, please wait or check later!" xml:space="preserve"> <source>You will be connected when your contact's device is online, please wait or check later!</source> + <target>Kişinizin cihazı çevrimiçi olduğunda bağlanacaksınız, lütfen bekleyin veya daha sonra kontrol edin!</target> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="You will be required to authenticate when you start or resume the app after 30 seconds in background." xml:space="preserve"> <source>You will be required to authenticate when you start or resume the app after 30 seconds in background.</source> + <target>Arka planda 30 saniye kaldıktan sonra uygulamayı başlattığınızda veya devam ettirdiğinizde kimlik doğrulaması yapmanız gerekecektir.</target> <note>No comment provided by engineer.</note> </trans-unit> - <trans-unit id="You will join a group this link refers to and connect to its group members." xml:space="preserve"> - <source>You will join a group this link refers to and connect to its group members.</source> + <trans-unit id="You will connect to all group members." xml:space="preserve"> + <source>You will connect to all group members.</source> + <target>Bütün grup üyelerine bağlanacaksın.</target> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="You will still receive calls and notifications from muted profiles when they are active." xml:space="preserve"> <source>You will still receive calls and notifications from muted profiles when they are active.</source> + <target>Aktif olduklarında sessize alınmış profillerden arama ve bildirim almaya devam edersiniz.</target> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="You will stop receiving messages from this group. Chat history will be preserved." xml:space="preserve"> <source>You will stop receiving messages from this group. Chat history will be preserved.</source> + <target>Bu gruptan artık mesaj almayacaksınız. Sohbet geçmişi korunacaktır.</target> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="You won't lose your contacts if you later delete your address." xml:space="preserve"> <source>You won't lose your contacts if you later delete your address.</source> + <target>Eğer sonradan bağlantınızı silseniz bile kişilerinizi kaybetmeyeceksiniz.</target> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="You're trying to invite contact with whom you've shared an incognito profile to the group in which you're using your main profile" xml:space="preserve"> <source>You're trying to invite contact with whom you've shared an incognito profile to the group in which you're using your main profile</source> + <target>Gizli bir profil paylaştığınız kişiyi ana profilinizi kullandığınız gruba davet etmeye çalışıyorsunuz</target> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="You're using an incognito profile for this group - to prevent sharing your main profile inviting contacts is not allowed" xml:space="preserve"> <source>You're using an incognito profile for this group - to prevent sharing your main profile inviting contacts is not allowed</source> + <target>Bu grup için gizli bir profil kullanıyorsunuz - ana profilinizi paylaşmayı önlemek için kişileri davet etmeye izin verilmiyor</target> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="Your %@ servers" xml:space="preserve"> <source>Your %@ servers</source> + <target>%@ sunucularınız</target> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="Your ICE servers" xml:space="preserve"> <source>Your ICE servers</source> + <target>ICE sunucularınız</target> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="Your SMP servers" xml:space="preserve"> <source>Your SMP servers</source> + <target>SMP sunucularınız</target> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="Your SimpleX address" xml:space="preserve"> <source>Your SimpleX address</source> + <target>SimpleX adresin</target> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="Your XFTP servers" xml:space="preserve"> <source>Your XFTP servers</source> + <target>XFTP sunucularınız</target> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="Your calls" xml:space="preserve"> <source>Your calls</source> + <target>Aramaların</target> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="Your chat database" xml:space="preserve"> <source>Your chat database</source> + <target>Sohbet veritabanınız</target> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="Your chat database is not encrypted - set passphrase to encrypt it." xml:space="preserve"> <source>Your chat database is not encrypted - set passphrase to encrypt it.</source> - <note>No comment provided by engineer.</note> - </trans-unit> - <trans-unit id="Your chat profile will be sent to group members" xml:space="preserve"> - <source>Your chat profile will be sent to group members</source> - <note>No comment provided by engineer.</note> - </trans-unit> - <trans-unit id="Your chat profile will be sent to your contact" xml:space="preserve"> - <source>Your chat profile will be sent to your contact</source> + <target>Sohbet veritabanınız şifrelenmemiş - şifrelemek için parola ayarlayın.</target> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="Your chat profiles" xml:space="preserve"> <source>Your chat profiles</source> + <target>Sohbet profillerin</target> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="Your contact needs to be online for the connection to complete. You can cancel this connection and remove the contact (and try later with a new link)." xml:space="preserve"> <source>Your contact needs to be online for the connection to complete. You can cancel this connection and remove the contact (and try later with a new link).</source> + <target>Bağlantının tamamlanması için kişinizin çevrimiçi olması gerekir. +Bu bağlantıyı iptal edebilir ve kişiyi kaldırabilirsiniz (ve daha sonra yeni bir bağlantıyla deneyebilirsiniz).</target> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="Your contact sent a file that is larger than currently supported maximum size (%@)." xml:space="preserve"> <source>Your contact sent a file that is larger than currently supported maximum size (%@).</source> + <target>Kişiniz şu anda desteklenen maksimum boyuttan (%@) daha büyük bir dosya gönderdi.</target> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="Your contacts can allow full message deletion." xml:space="preserve"> <source>Your contacts can allow full message deletion.</source> - <note>No comment provided by engineer.</note> - </trans-unit> - <trans-unit id="Your contacts in SimpleX will see it. You can change it in Settings." xml:space="preserve"> - <source>Your contacts in SimpleX will see it. -You can change it in Settings.</source> + <target>Kişileriniz tam mesaj silme işlemine izin verebilir.</target> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="Your contacts will remain connected." xml:space="preserve"> <source>Your contacts will remain connected.</source> + <target>Kişileriniz bağlı kalacaktır.</target> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="Your current chat database will be DELETED and REPLACED with the imported one." xml:space="preserve"> <source>Your current chat database will be DELETED and REPLACED with the imported one.</source> + <target>Mevcut sohbet veritabanınız SİLİNECEK ve içe aktarılan veritabanıyla DEĞİŞTİRİLECEKTİR.</target> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="Your current profile" xml:space="preserve"> <source>Your current profile</source> + <target>Mevcut profiliniz</target> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="Your preferences" xml:space="preserve"> <source>Your preferences</source> + <target>Tercihleriniz</target> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="Your privacy" xml:space="preserve"> <source>Your privacy</source> + <target>Gizliliğiniz</target> + <note>No comment provided by engineer.</note> + </trans-unit> + <trans-unit id="Your profile" xml:space="preserve"> + <source>Your profile</source> + <target>Profiliniz</target> + <note>No comment provided by engineer.</note> + </trans-unit> + <trans-unit id="Your profile **%@** will be shared." xml:space="preserve"> + <source>Your profile **%@** will be shared.</source> + <target>Profiliniz **%@** paylaşılacaktır.</target> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="Your profile is stored on your device and shared only with your contacts. SimpleX servers cannot see your profile." xml:space="preserve"> <source>Your profile is stored on your device and shared only with your contacts. SimpleX servers cannot see your profile.</source> - <note>No comment provided by engineer.</note> - </trans-unit> - <trans-unit id="Your profile will be sent to the contact that you received this link from" xml:space="preserve"> - <source>Your profile will be sent to the contact that you received this link from</source> + <target>Profiliniz cihazınızda saklanır ve sadece kişilerinizle paylaşılır. +SimpleX sunucuları profilinizi göremez.</target> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="Your profile, contacts and delivered messages are stored on your device." xml:space="preserve"> <source>Your profile, contacts and delivered messages are stored on your device.</source> + <target>Profiliniz, kişileriniz ve gönderilmiş mesajlar cihazınızda saklanır.</target> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="Your random profile" xml:space="preserve"> <source>Your random profile</source> + <target>Rasgele profiliniz</target> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="Your server" xml:space="preserve"> <source>Your server</source> + <target>Sunucunuz</target> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="Your server address" xml:space="preserve"> <source>Your server address</source> + <target>Sunucu adresiniz</target> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="Your settings" xml:space="preserve"> <source>Your settings</source> + <target>Ayarlarınız</target> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="[Contribute](https://github.com/simplex-chat/simplex-chat#contribute)" xml:space="preserve"> <source>[Contribute](https://github.com/simplex-chat/simplex-chat#contribute)</source> + <target>[Katkıda bulun](https://github.com/simplex-chat/simplex-chat#contribute)</target> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="[Send us email](mailto:chat@simplex.chat)" xml:space="preserve"> <source>[Send us email](mailto:chat@simplex.chat)</source> + <target>[Bize e-posta gönder](mailto:chat@simplex.chat)</target> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="[Star on GitHub](https://github.com/simplex-chat/simplex-chat)" xml:space="preserve"> <source>[Star on GitHub](https://github.com/simplex-chat/simplex-chat)</source> + <target>[Bize GitHub'da yıldız verin](https://github.com/simplex-chat/simplex-chat)</target> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="_italic_" xml:space="preserve"> <source>\_italic_</source> + <target>\_italik_</target> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="`a + b`" xml:space="preserve"> <source>\`a + b`</source> + <target>\`a + b`</target> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="above, then choose:" xml:space="preserve"> <source>above, then choose:</source> + <target>yukarı çıkın, ardından seçin:</target> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="accepted call" xml:space="preserve"> <source>accepted call</source> + <target>kabul edilen arama</target> <note>call status</note> </trans-unit> <trans-unit id="admin" xml:space="preserve"> <source>admin</source> + <target>yönetici</target> <note>member role</note> </trans-unit> <trans-unit id="agreeing encryption for %@…" xml:space="preserve"> <source>agreeing encryption for %@…</source> + <target>%@ için şifreleme kabul ediliyor…</target> <note>chat item text</note> </trans-unit> <trans-unit id="agreeing encryption…" xml:space="preserve"> <source>agreeing encryption…</source> + <target>şifreleme kabul ediliyor…</target> <note>chat item text</note> </trans-unit> <trans-unit id="always" xml:space="preserve"> <source>always</source> + <target>her zaman</target> <note>pref value</note> </trans-unit> + <trans-unit id="and %lld other events" xml:space="preserve"> + <source>and %lld other events</source> + <target>ve %lld diğer etkinlikler</target> + <note>No comment provided by engineer.</note> + </trans-unit> <trans-unit id="audio call (not e2e encrypted)" xml:space="preserve"> <source>audio call (not e2e encrypted)</source> + <target>sesli arama (uçtan uca şifreli değil)</target> <note>No comment provided by engineer.</note> </trans-unit> + <trans-unit id="author" xml:space="preserve"> + <source>author</source> + <target>yetkili</target> + <note>member role</note> + </trans-unit> <trans-unit id="bad message ID" xml:space="preserve"> <source>bad message ID</source> + <target>kötü mesaj kimliği</target> <note>integrity error chat item</note> </trans-unit> <trans-unit id="bad message hash" xml:space="preserve"> <source>bad message hash</source> + <target>kötü mesaj hash'i</target> <note>integrity error chat item</note> </trans-unit> + <trans-unit id="blocked" xml:space="preserve"> + <source>blocked</source> + <target>engellendi</target> + <note>No comment provided by engineer.</note> + </trans-unit> + <trans-unit id="blocked %@" xml:space="preserve"> + <source>blocked %@</source> + <note>rcv group event chat item</note> + </trans-unit> + <trans-unit id="blocked by admin" xml:space="preserve"> + <source>blocked by admin</source> + <note>blocked chat item</note> + </trans-unit> <trans-unit id="bold" xml:space="preserve"> <source>bold</source> + <target>kalın</target> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="call error" xml:space="preserve"> <source>call error</source> + <target>arama hatası</target> <note>call status</note> </trans-unit> <trans-unit id="call in progress" xml:space="preserve"> <source>call in progress</source> + <target>arama yapılıyor</target> <note>call status</note> </trans-unit> <trans-unit id="calling…" xml:space="preserve"> <source>calling…</source> + <target>aranıyor…</target> <note>call status</note> </trans-unit> <trans-unit id="cancelled %@" xml:space="preserve"> <source>cancelled %@</source> + <target>%@ iptal edildi</target> <note>feature offered item</note> </trans-unit> <trans-unit id="changed address for you" xml:space="preserve"> <source>changed address for you</source> + <target>senin için adres değiştirildi</target> <note>chat item text</note> </trans-unit> <trans-unit id="changed role of %@ to %@" xml:space="preserve"> <source>changed role of %1$@ to %2$@</source> + <target>1$@ rolünü %2$@ olarak değiştirdi</target> <note>rcv group event chat item</note> </trans-unit> <trans-unit id="changed your role to %@" xml:space="preserve"> <source>changed your role to %@</source> + <target>rolünü %@ olarak değiştirdi</target> <note>rcv group event chat item</note> </trans-unit> <trans-unit id="changing address for %@…" xml:space="preserve"> <source>changing address for %@…</source> + <target>%@ için adres değiştiriliyor…</target> <note>chat item text</note> </trans-unit> <trans-unit id="changing address…" xml:space="preserve"> <source>changing address…</source> + <target>adres değiştiriliyor…</target> <note>chat item text</note> </trans-unit> <trans-unit id="colored" xml:space="preserve"> <source>colored</source> + <target>renklendirilmiş</target> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="complete" xml:space="preserve"> <source>complete</source> + <target>tamamlandı</target> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="connect to SimpleX Chat developers." xml:space="preserve"> <source>connect to SimpleX Chat developers.</source> + <target>SimpleX Chat geliştiricilerine bağlan.</target> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="connected" xml:space="preserve"> <source>connected</source> + <target>bağlanıldı</target> <note>No comment provided by engineer.</note> </trans-unit> + <trans-unit id="connected directly" xml:space="preserve"> + <source>connected directly</source> + <target>doğrudan bağlandı</target> + <note>rcv group event chat item</note> + </trans-unit> <trans-unit id="connecting" xml:space="preserve"> <source>connecting</source> + <target>bağlanılıyor</target> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="connecting (accepted)" xml:space="preserve"> <source>connecting (accepted)</source> + <target>bağlanılıyor (onaylandı)</target> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="connecting (announced)" xml:space="preserve"> <source>connecting (announced)</source> + <target>bağlanılıyor (duyuruldu)</target> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="connecting (introduced)" xml:space="preserve"> <source>connecting (introduced)</source> + <target>bağlanılıyor (tanıtıldı)</target> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="connecting (introduction invitation)" xml:space="preserve"> <source>connecting (introduction invitation)</source> + <target>bağlanılıyor (tanıtılma isteği)</target> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="connecting call" xml:space="preserve"> <source>connecting call…</source> + <target>aramaya bağlanılıyor…</target> <note>call status</note> </trans-unit> <trans-unit id="connecting…" xml:space="preserve"> <source>connecting…</source> + <target>bağlanılıyor…</target> <note>chat list item title</note> </trans-unit> <trans-unit id="connection established" xml:space="preserve"> <source>connection established</source> + <target>bağlantı kuruldu</target> <note>chat list item title (it should not be shown</note> </trans-unit> <trans-unit id="connection:%@" xml:space="preserve"> <source>connection:%@</source> + <target>bağlantı:%@</target> <note>connection information</note> </trans-unit> + <trans-unit id="contact %@ changed to %@" xml:space="preserve"> + <source>contact %1$@ changed to %2$@</source> + <note>profile update event chat item</note> + </trans-unit> <trans-unit id="contact has e2e encryption" xml:space="preserve"> <source>contact has e2e encryption</source> + <target>kişi uçtan uca şifrelemeye sahiptir</target> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="contact has no e2e encryption" xml:space="preserve"> <source>contact has no e2e encryption</source> + <target>kişi uçtan uca şifrelemeye sahip değildir</target> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="creator" xml:space="preserve"> <source>creator</source> + <target>oluşturan</target> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="custom" xml:space="preserve"> <source>custom</source> + <target>özel</target> <note>dropdown time picker choice</note> </trans-unit> <trans-unit id="database version is newer than the app, but no down migration for: %@" xml:space="preserve"> <source>database version is newer than the app, but no down migration for: %@</source> + <target>veritabanı sürümü uygulamadan daha yeni, ancak aşağı geçiş yok: %@</target> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="days" xml:space="preserve"> <source>days</source> + <target>gün</target> <note>time unit</note> </trans-unit> <trans-unit id="default (%@)" xml:space="preserve"> <source>default (%@)</source> + <target>varsayılan (%@)</target> <note>pref value</note> </trans-unit> <trans-unit id="default (no)" xml:space="preserve"> <source>default (no)</source> + <target>varsayılan (hayır)</target> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="default (yes)" xml:space="preserve"> <source>default (yes)</source> + <target>varsayılan (evet)</target> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="deleted" xml:space="preserve"> <source>deleted</source> + <target>silindi</target> <note>deleted chat item</note> </trans-unit> + <trans-unit id="deleted contact" xml:space="preserve"> + <source>deleted contact</source> + <target>silinmiş kişi</target> + <note>rcv direct event chat item</note> + </trans-unit> <trans-unit id="deleted group" xml:space="preserve"> <source>deleted group</source> + <target>silinmiş grup</target> <note>rcv group event chat item</note> </trans-unit> <trans-unit id="different migration in the app/database: %@ / %@" xml:space="preserve"> <source>different migration in the app/database: %@ / %@</source> + <target>uygulamada/veritabanında farklı geçiş: %@ / %@</target> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="direct" xml:space="preserve"> <source>direct</source> + <target>doğrudan</target> <note>connection level description</note> </trans-unit> + <trans-unit id="disabled" xml:space="preserve"> + <source>disabled</source> + <target>devre dışı</target> + <note>No comment provided by engineer.</note> + </trans-unit> <trans-unit id="duplicate message" xml:space="preserve"> <source>duplicate message</source> + <target>yinelenen mesaj</target> <note>integrity error chat item</note> </trans-unit> <trans-unit id="e2e encrypted" xml:space="preserve"> <source>e2e encrypted</source> + <target>uçtan uca şifrelenmiş</target> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="enabled" xml:space="preserve"> <source>enabled</source> + <target>etkin</target> <note>enabled status</note> </trans-unit> <trans-unit id="enabled for contact" xml:space="preserve"> <source>enabled for contact</source> + <target>konuşulan kişi için etkinleşti</target> <note>enabled status</note> </trans-unit> <trans-unit id="enabled for you" xml:space="preserve"> <source>enabled for you</source> + <target>senin için etkinleştirildi</target> <note>enabled status</note> </trans-unit> <trans-unit id="encryption agreed" xml:space="preserve"> <source>encryption agreed</source> + <target>şifreleme kabul edildi</target> <note>chat item text</note> </trans-unit> <trans-unit id="encryption agreed for %@" xml:space="preserve"> <source>encryption agreed for %@</source> + <target>şifreleme %@ için kabul edildi</target> <note>chat item text</note> </trans-unit> <trans-unit id="encryption ok" xml:space="preserve"> <source>encryption ok</source> + <target>şifreleme etkin</target> <note>chat item text</note> </trans-unit> <trans-unit id="encryption ok for %@" xml:space="preserve"> <source>encryption ok for %@</source> + <target>şifreleme %@ için etkin</target> <note>chat item text</note> </trans-unit> <trans-unit id="encryption re-negotiation allowed" xml:space="preserve"> <source>encryption re-negotiation allowed</source> + <target>şifrelemenin yeniden anlaşmasına izin verildi</target> <note>chat item text</note> </trans-unit> <trans-unit id="encryption re-negotiation allowed for %@" xml:space="preserve"> <source>encryption re-negotiation allowed for %@</source> + <target>şifrelemenin yeniden anlaşmasına %@ için izin verildi</target> <note>chat item text</note> </trans-unit> <trans-unit id="encryption re-negotiation required" xml:space="preserve"> <source>encryption re-negotiation required</source> + <target>şifrelemenin yeniden anlaşması gerekiyor</target> <note>chat item text</note> </trans-unit> <trans-unit id="encryption re-negotiation required for %@" xml:space="preserve"> <source>encryption re-negotiation required for %@</source> + <target>şifrelemenin yeniden anlaşması %@ için gerekiyor</target> <note>chat item text</note> </trans-unit> <trans-unit id="ended" xml:space="preserve"> <source>ended</source> + <target>bitti</target> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="ended call %@" xml:space="preserve"> <source>ended call %@</source> + <target>%@ araması bitti</target> <note>call status</note> </trans-unit> <trans-unit id="error" xml:space="preserve"> <source>error</source> + <target>hata</target> + <note>No comment provided by engineer.</note> + </trans-unit> + <trans-unit id="event happened" xml:space="preserve"> + <source>event happened</source> + <target>etkinliği yaşandı</target> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="group deleted" xml:space="preserve"> <source>group deleted</source> + <target>grup silindi</target> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="group profile updated" xml:space="preserve"> <source>group profile updated</source> + <target>grup profili güncellendi</target> <note>snd group event chat item</note> </trans-unit> <trans-unit id="hours" xml:space="preserve"> <source>hours</source> + <target>saat</target> <note>time unit</note> </trans-unit> <trans-unit id="iOS Keychain is used to securely store passphrase - it allows receiving push notifications." xml:space="preserve"> <source>iOS Keychain is used to securely store passphrase - it allows receiving push notifications.</source> + <target>iOS Anahtar Zinciri parolayı güvenli bir şekilde saklamak için kullanılır - anlık bildirimlerin alınmasını sağlar.</target> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="iOS Keychain will be used to securely store passphrase after you restart the app or change passphrase - it will allow receiving push notifications." xml:space="preserve"> <source>iOS Keychain will be used to securely store passphrase after you restart the app or change passphrase - it will allow receiving push notifications.</source> + <target>iOS Anahtar Zinciri, uygulamayı yeniden başlattıktan veya parolayı değiştirdikten sonra parolayı güvenli bir şekilde saklamak için kullanılacaktır - anlık bildirimlerin alınmasına izin verecektir.</target> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="incognito via contact address link" xml:space="preserve"> <source>incognito via contact address link</source> + <target>kişi bağlantı linki aracılığıyla gizli</target> <note>chat list item description</note> </trans-unit> <trans-unit id="incognito via group link" xml:space="preserve"> <source>incognito via group link</source> + <target>grup bağlantısı aracılığıyla gizli</target> <note>chat list item description</note> </trans-unit> <trans-unit id="incognito via one-time link" xml:space="preserve"> <source>incognito via one-time link</source> + <target>tek seferlik bağlantısı aracılığıyla gizli</target> <note>chat list item description</note> </trans-unit> <trans-unit id="indirect (%d)" xml:space="preserve"> <source>indirect (%d)</source> + <target>dolaylı (%d)</target> <note>connection level description</note> </trans-unit> <trans-unit id="invalid chat" xml:space="preserve"> <source>invalid chat</source> + <target>geçersi̇z sohbet</target> <note>invalid chat data</note> </trans-unit> <trans-unit id="invalid chat data" xml:space="preserve"> <source>invalid chat data</source> + <target>geçersi̇z sohbet verisi</target> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="invalid data" xml:space="preserve"> <source>invalid data</source> + <target>geçersiz veri</target> <note>invalid chat item</note> </trans-unit> <trans-unit id="invitation to group %@" xml:space="preserve"> <source>invitation to group %@</source> + <target>%@ grubuna davet</target> <note>group name</note> </trans-unit> <trans-unit id="invited" xml:space="preserve"> <source>invited</source> + <target>davet edildi</target> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="invited %@" xml:space="preserve"> <source>invited %@</source> + <target>%@ a davet edildi</target> <note>rcv group event chat item</note> </trans-unit> <trans-unit id="invited to connect" xml:space="preserve"> <source>invited to connect</source> + <target>bağlanmaya davet edildi</target> <note>chat list item title</note> </trans-unit> <trans-unit id="invited via your group link" xml:space="preserve"> <source>invited via your group link</source> + <target>grup bağlantınız üzerinden davet edildi</target> <note>rcv group event chat item</note> </trans-unit> <trans-unit id="italic" xml:space="preserve"> <source>italic</source> + <target>italik</target> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="join as %@" xml:space="preserve"> <source>join as %@</source> + <target>%@ olarak katıl</target> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="left" xml:space="preserve"> <source>left</source> + <target>ayrıldı</target> <note>rcv group event chat item</note> </trans-unit> <trans-unit id="marked deleted" xml:space="preserve"> <source>marked deleted</source> + <target>silinmiş olarak işaretlenmiş</target> <note>marked deleted chat item preview text</note> </trans-unit> <trans-unit id="member" xml:space="preserve"> <source>member</source> + <target>üye</target> <note>member role</note> </trans-unit> + <trans-unit id="member %@ changed to %@" xml:space="preserve"> + <source>member %1$@ changed to %2$@</source> + <note>profile update event chat item</note> + </trans-unit> <trans-unit id="member connected" xml:space="preserve"> <source>connected</source> + <target>bağlanıldı</target> <note>rcv group event chat item</note> </trans-unit> - <trans-unit id="message received" xml:space="preserve" approved="no"> + <trans-unit id="message received" xml:space="preserve"> <source>message received</source> - <target state="translated">mesaj alındı</target> + <target>mesaj alındı</target> <note>notification</note> </trans-unit> - <trans-unit id="minutes" xml:space="preserve" approved="no"> + <trans-unit id="minutes" xml:space="preserve"> <source>minutes</source> - <target state="translated">dakikalar</target> + <target>dakikalar</target> <note>time unit</note> </trans-unit> - <trans-unit id="missed call" xml:space="preserve" approved="no"> + <trans-unit id="missed call" xml:space="preserve"> <source>missed call</source> - <target state="translated">cevapsız arama</target> + <target>cevapsız arama</target> <note>call status</note> </trans-unit> - <trans-unit id="moderated" xml:space="preserve" approved="no"> + <trans-unit id="moderated" xml:space="preserve"> <source>moderated</source> - <target state="needs-translation">moderated</target> + <target>yönetildi</target> <note>moderated chat item</note> </trans-unit> - <trans-unit id="moderated by %@" xml:space="preserve" approved="no"> + <trans-unit id="moderated by %@" xml:space="preserve"> <source>moderated by %@</source> - <target state="translated">%@ tarafından yönetilmekte</target> + <target>%@ tarafından yönetilmekte</target> <note>No comment provided by engineer.</note> </trans-unit> - <trans-unit id="months" xml:space="preserve" approved="no"> + <trans-unit id="months" xml:space="preserve"> <source>months</source> - <target state="translated">aylar</target> + <target>aylar</target> <note>time unit</note> </trans-unit> <trans-unit id="never" xml:space="preserve"> <source>never</source> + <target>asla</target> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="new message" xml:space="preserve"> <source>new message</source> + <target>yeni mesaj</target> <note>notification</note> </trans-unit> <trans-unit id="no" xml:space="preserve"> <source>no</source> + <target>hayır</target> <note>pref value</note> </trans-unit> <trans-unit id="no e2e encryption" xml:space="preserve"> <source>no e2e encryption</source> + <target>uçtan uca şifreleme yok</target> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="no text" xml:space="preserve"> <source>no text</source> + <target>metin yok</target> <note>copied message info in history</note> </trans-unit> <trans-unit id="observer" xml:space="preserve"> <source>observer</source> + <target>gözlemci</target> <note>member role</note> </trans-unit> <trans-unit id="off" xml:space="preserve"> <source>off</source> + <target>kapalı</target> <note>enabled status - group pref value</note> + group pref value + time to disappear</note> </trans-unit> <trans-unit id="offered %@" xml:space="preserve"> <source>offered %@</source> + <target>%@ teklif edildi</target> <note>feature offered item</note> </trans-unit> <trans-unit id="offered %@: %@" xml:space="preserve"> <source>offered %1$@: %2$@</source> + <target>%1$@: %2$@ teklif etti</target> <note>feature offered item</note> </trans-unit> <trans-unit id="on" xml:space="preserve"> <source>on</source> + <target>açık</target> <note>group pref value</note> </trans-unit> - <trans-unit id="or chat with the developers" xml:space="preserve"> - <source>or chat with the developers</source> - <note>No comment provided by engineer.</note> - </trans-unit> <trans-unit id="owner" xml:space="preserve"> <source>owner</source> + <target>sahip</target> <note>member role</note> </trans-unit> <trans-unit id="peer-to-peer" xml:space="preserve"> <source>peer-to-peer</source> + <target>eşler arası</target> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="received answer…" xml:space="preserve"> <source>received answer…</source> + <target>alınan cevap…</target> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="received confirmation…" xml:space="preserve"> <source>received confirmation…</source> + <target>onaylama alındı…</target> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="rejected call" xml:space="preserve"> <source>rejected call</source> + <target>geri çevrilmiş çağrı</target> <note>call status</note> </trans-unit> <trans-unit id="removed" xml:space="preserve"> <source>removed</source> + <target>kaldırıldı</target> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="removed %@" xml:space="preserve"> <source>removed %@</source> + <target>%@ kaldırıldı</target> <note>rcv group event chat item</note> </trans-unit> + <trans-unit id="removed contact address" xml:space="preserve"> + <source>removed contact address</source> + <note>profile update event chat item</note> + </trans-unit> + <trans-unit id="removed profile picture" xml:space="preserve"> + <source>removed profile picture</source> + <note>profile update event chat item</note> + </trans-unit> <trans-unit id="removed you" xml:space="preserve"> <source>removed you</source> + <target>sen kaldırıldın</target> <note>rcv group event chat item</note> </trans-unit> <trans-unit id="sec" xml:space="preserve"> <source>sec</source> + <target>sn</target> <note>network option</note> </trans-unit> <trans-unit id="seconds" xml:space="preserve"> <source>seconds</source> + <target>saniye</target> <note>time unit</note> </trans-unit> <trans-unit id="secret" xml:space="preserve"> <source>secret</source> + <target>gizli</target> <note>No comment provided by engineer.</note> </trans-unit> - <trans-unit id="security code changed" xml:space="preserve" approved="no"> + <trans-unit id="security code changed" xml:space="preserve"> <source>security code changed</source> - <target state="translated">güvenlik kodu değiştirildi</target> + <target>güvenlik kodu değiştirildi</target> <note>chat item text</note> </trans-unit> - <trans-unit id="starting…" xml:space="preserve" approved="no"> + <trans-unit id="send direct message" xml:space="preserve"> + <source>send direct message</source> + <target>doğrudan mesaj gönder</target> + <note>No comment provided by engineer.</note> + </trans-unit> + <trans-unit id="set new contact address" xml:space="preserve"> + <source>set new contact address</source> + <note>profile update event chat item</note> + </trans-unit> + <trans-unit id="set new profile picture" xml:space="preserve"> + <source>set new profile picture</source> + <note>profile update event chat item</note> + </trans-unit> + <trans-unit id="starting…" xml:space="preserve"> <source>starting…</source> - <target state="translated">başlıyor…</target> + <target>başlatılıyor…</target> <note>No comment provided by engineer.</note> </trans-unit> - <trans-unit id="strike" xml:space="preserve" approved="no"> + <trans-unit id="strike" xml:space="preserve"> <source>strike</source> - <target state="needs-translation">strike</target> + <target>grev</target> <note>No comment provided by engineer.</note> </trans-unit> - <trans-unit id="this contact" xml:space="preserve" approved="no"> + <trans-unit id="this contact" xml:space="preserve"> <source>this contact</source> - <target state="translated">Bu kişi</target> + <target>Bu kişi</target> <note>notification title</note> </trans-unit> - <trans-unit id="unknown" xml:space="preserve" approved="no"> - <source>unknown</source> - <target state="translated">bilinmeyen</target> - <note>connection info</note> - </trans-unit> - <trans-unit id="updated group profile" xml:space="preserve" approved="no"> - <source>updated group profile</source> - <target state="translated">grup profili güncellendi</target> + <trans-unit id="unblocked %@" xml:space="preserve"> + <source>unblocked %@</source> <note>rcv group event chat item</note> </trans-unit> - <trans-unit id="v%@ (%@)" xml:space="preserve" approved="no"> + <trans-unit id="unknown" xml:space="preserve"> + <source>unknown</source> + <target>bilinmeyen</target> + <note>connection info</note> + </trans-unit> + <trans-unit id="unknown status" xml:space="preserve"> + <source>unknown status</source> + <note>No comment provided by engineer.</note> + </trans-unit> + <trans-unit id="updated group profile" xml:space="preserve"> + <source>updated group profile</source> + <target>grup profili güncellendi</target> + <note>rcv group event chat item</note> + </trans-unit> + <trans-unit id="updated profile" xml:space="preserve"> + <source>updated profile</source> + <note>profile update event chat item</note> + </trans-unit> + <trans-unit id="v%@" xml:space="preserve"> + <source>v%@</source> + <target>v%@</target> + <note>No comment provided by engineer.</note> + </trans-unit> + <trans-unit id="v%@ (%@)" xml:space="preserve"> <source>v%@ (%@)</source> - <target state="translated">v%@ (%@)</target> + <target>v%@ (%@)</target> <note>No comment provided by engineer.</note> </trans-unit> - <trans-unit id="via contact address link" xml:space="preserve" approved="no"> + <trans-unit id="via contact address link" xml:space="preserve"> <source>via contact address link</source> - <target state="translated">bağlantı adres uzantısı ile</target> + <target>bağlantı adres uzantısı ile</target> <note>chat list item description</note> </trans-unit> - <trans-unit id="via group link" xml:space="preserve" approved="no"> + <trans-unit id="via group link" xml:space="preserve"> <source>via group link</source> - <target state="translated">grup bağlantısı ile</target> + <target>grup bağlantısı ile</target> <note>chat list item description</note> </trans-unit> - <trans-unit id="via one-time link" xml:space="preserve" approved="no"> + <trans-unit id="via one-time link" xml:space="preserve"> <source>via one-time link</source> - <target state="translated">tek kullanımlık bağlantısı ile</target> + <target>tek kullanımlık bağlantısı ile</target> <note>chat list item description</note> </trans-unit> - <trans-unit id="via relay" xml:space="preserve" approved="no"> + <trans-unit id="via relay" xml:space="preserve"> <source>via relay</source> - <target state="needs-translation">via relay</target> + <target>yönlendirici aracılığıyla</target> <note>No comment provided by engineer.</note> </trans-unit> - <trans-unit id="video call (not e2e encrypted)" xml:space="preserve" approved="no"> + <trans-unit id="video call (not e2e encrypted)" xml:space="preserve"> <source>video call (not e2e encrypted)</source> - <target state="translated">Görüntülü arama (şifrelenmiş değil)</target> + <target>Görüntülü arama (şifrelenmiş değil)</target> <note>No comment provided by engineer.</note> </trans-unit> - <trans-unit id="waiting for answer…" xml:space="preserve" approved="no"> + <trans-unit id="waiting for answer…" xml:space="preserve"> <source>waiting for answer…</source> - <target state="translated">cevap bekleniyor…</target> + <target>cevap bekleniyor…</target> <note>No comment provided by engineer.</note> </trans-unit> - <trans-unit id="waiting for confirmation…" xml:space="preserve" approved="no"> + <trans-unit id="waiting for confirmation…" xml:space="preserve"> <source>waiting for confirmation…</source> - <target state="translated">onay bekleniyor…</target> + <target>onay bekleniyor…</target> <note>No comment provided by engineer.</note> </trans-unit> - <trans-unit id="wants to connect to you!" xml:space="preserve" approved="no"> + <trans-unit id="wants to connect to you!" xml:space="preserve"> <source>wants to connect to you!</source> - <target state="translated">bağlanmak istiyor!</target> + <target>bağlanmak istiyor!</target> <note>No comment provided by engineer.</note> </trans-unit> - <trans-unit id="weeks" xml:space="preserve" approved="no"> + <trans-unit id="weeks" xml:space="preserve"> <source>weeks</source> - <target state="translated">haftalar</target> + <target>haftalar</target> <note>time unit</note> </trans-unit> - <trans-unit id="yes" xml:space="preserve" approved="no"> + <trans-unit id="yes" xml:space="preserve"> <source>yes</source> - <target state="translated">evet</target> + <target>evet</target> <note>pref value</note> </trans-unit> - <trans-unit id="you are invited to group" xml:space="preserve" approved="no"> + <trans-unit id="you are invited to group" xml:space="preserve"> <source>you are invited to group</source> - <target state="translated">gruba davet edildiniz</target> + <target>gruba davet edildiniz</target> <note>No comment provided by engineer.</note> </trans-unit> - <trans-unit id="you are observer" xml:space="preserve" approved="no"> + <trans-unit id="you are observer" xml:space="preserve"> <source>you are observer</source> - <target state="translated">gözlemcisiniz</target> + <target>gözlemcisiniz</target> <note>No comment provided by engineer.</note> </trans-unit> - <trans-unit id="you changed address" xml:space="preserve" approved="no"> + <trans-unit id="you blocked %@" xml:space="preserve"> + <source>you blocked %@</source> + <note>snd group event chat item</note> + </trans-unit> + <trans-unit id="you changed address" xml:space="preserve"> <source>you changed address</source> - <target state="translated">adresinizi değiştirdiniz</target> + <target>adresinizi değiştirdiniz</target> <note>chat item text</note> </trans-unit> - <trans-unit id="you changed address for %@" xml:space="preserve" approved="no"> + <trans-unit id="you changed address for %@" xml:space="preserve"> <source>you changed address for %@</source> - <target state="translated">adresinizi %@ ile değiştirdiniz</target> + <target>adresinizi %@ ile değiştirdiniz</target> <note>chat item text</note> </trans-unit> - <trans-unit id="you changed role for yourself to %@" xml:space="preserve" approved="no"> + <trans-unit id="you changed role for yourself to %@" xml:space="preserve"> <source>you changed role for yourself to %@</source> - <target state="translated">kişisel yetkinizi %@ olarak değiştirdiniz</target> + <target>kişisel yetkinizi %@ olarak değiştirdiniz</target> <note>snd group event chat item</note> </trans-unit> - <trans-unit id="you changed role of %@ to %@" xml:space="preserve" approved="no"> + <trans-unit id="you changed role of %@ to %@" xml:space="preserve"> <source>you changed role of %1$@ to %2$@</source> - <target state="translated">%1$@'in yetkisini %2$@ olarak değiştirdiniz</target> + <target>%1$@'in yetkisini %2$@ olarak değiştirdiniz</target> <note>snd group event chat item</note> </trans-unit> - <trans-unit id="you left" xml:space="preserve" approved="no"> + <trans-unit id="you left" xml:space="preserve"> <source>you left</source> - <target state="translated">terk ettiniz</target> + <target>terk ettiniz</target> <note>snd group event chat item</note> </trans-unit> - <trans-unit id="you removed %@" xml:space="preserve" approved="no"> + <trans-unit id="you removed %@" xml:space="preserve"> <source>you removed %@</source> - <target state="translated">%@'yi çıkarttınız</target> + <target>%@'yi çıkarttınız</target> <note>snd group event chat item</note> </trans-unit> - <trans-unit id="you shared one-time link" xml:space="preserve" approved="no"> + <trans-unit id="you shared one-time link" xml:space="preserve"> <source>you shared one-time link</source> - <target state="translated">tek kullanımlık bağlantınızı paylaştınız</target> + <target>tek kullanımlık bağlantınızı paylaştınız</target> <note>chat list item description</note> </trans-unit> - <trans-unit id="you shared one-time link incognito" xml:space="preserve" approved="no"> + <trans-unit id="you shared one-time link incognito" xml:space="preserve"> <source>you shared one-time link incognito</source> - <target state="translated">tek kullanımlık link paylaştınız gizli</target> + <target>tek kullanımlık link paylaştınız gizli</target> <note>chat list item description</note> </trans-unit> - <trans-unit id="you: " xml:space="preserve" approved="no"> + <trans-unit id="you unblocked %@" xml:space="preserve"> + <source>you unblocked %@</source> + <note>snd group event chat item</note> + </trans-unit> + <trans-unit id="you: " xml:space="preserve"> <source>you: </source> - <target state="translated">sen: </target> + <target>sen: </target> <note>No comment provided by engineer.</note> </trans-unit> - <trans-unit id="~strike~" xml:space="preserve" approved="no"> + <trans-unit id="~strike~" xml:space="preserve"> <source>\~strike~</source> - <target state="needs-translation">\~strike~</target> + <target>\~strike~</target> <note>No comment provided by engineer.</note> </trans-unit> </body> </file> <file original="en.lproj/SimpleX--iOS--InfoPlist.strings" source-language="en" target-language="tr" datatype="plaintext"> <header> - <tool tool-id="com.apple.dt.xcode" tool-name="Xcode" tool-version="14.3.1" build-num="14E300c"/> + <tool tool-id="com.apple.dt.xcode" tool-name="Xcode" tool-version="15.0" build-num="15A240d"/> </header> <body> - <trans-unit id="CFBundleName" xml:space="preserve" approved="no"> + <trans-unit id="CFBundleName" xml:space="preserve"> <source>SimpleX</source> - <target state="translated">SimpleX</target> + <target>SimpleX</target> <note>Bundle name</note> </trans-unit> <trans-unit id="NSCameraUsageDescription" xml:space="preserve"> <source>SimpleX needs camera access to scan QR codes to connect to other users and for video calls.</source> + <target>SimpleX, diğer kullanıcılara bağlanmak amacıyla QR kodlarını taramak ve görüntülü aramalar için kamera erişimine ihtiyaç duyar.</target> <note>Privacy - Camera Usage Description</note> </trans-unit> <trans-unit id="NSFaceIDUsageDescription" xml:space="preserve"> <source>SimpleX uses Face ID for local authentication</source> + <target>SimpleX yerel kimlik doğrulama için Face ID kullanır</target> <note>Privacy - Face ID Usage Description</note> </trans-unit> + <trans-unit id="NSLocalNetworkUsageDescription" xml:space="preserve"> + <source>SimpleX uses local network access to allow using user chat profile via desktop app on the same network.</source> + <target>SimpleX, aynı ağdaki masaüstü uygulaması aracılığıyla kullanıcı sohbet profilinin kullanılmasına izin vermek için yerel ağ erişimini kullanır.</target> + <note>Privacy - Local Network Usage Description</note> + </trans-unit> <trans-unit id="NSMicrophoneUsageDescription" xml:space="preserve"> <source>SimpleX needs microphone access for audio and video calls, and to record voice messages.</source> + <target>SimpleX'in sesli ve görüntülü aramalar ve sesli mesajları kaydetmek için mikrofon erişimine ihtiyacı vardır.</target> <note>Privacy - Microphone Usage Description</note> </trans-unit> <trans-unit id="NSPhotoLibraryAddUsageDescription" xml:space="preserve"> <source>SimpleX needs access to Photo Library for saving captured and received media</source> + <target>SimpleX'in çekilen ve alınan medyayı kaydetmek için Fotoğraf Kitaplığı'na erişmesi gerekir</target> <note>Privacy - Photo Library Additions Usage Description</note> </trans-unit> </body> </file> <file original="SimpleX NSE/en.lproj/InfoPlist.strings" source-language="en" target-language="tr" datatype="plaintext"> <header> - <tool tool-id="com.apple.dt.xcode" tool-name="Xcode" tool-version="14.3.1" build-num="14E300c"/> + <tool tool-id="com.apple.dt.xcode" tool-name="Xcode" tool-version="15.0" build-num="15A240d"/> </header> <body> <trans-unit id="CFBundleDisplayName" xml:space="preserve"> <source>SimpleX NSE</source> + <target>SimpleX NSE</target> <note>Bundle display name</note> </trans-unit> <trans-unit id="CFBundleName" xml:space="preserve"> <source>SimpleX NSE</source> + <target>SimpleX NSE</target> <note>Bundle name</note> </trans-unit> <trans-unit id="NSHumanReadableCopyright" xml:space="preserve"> <source>Copyright © 2022 SimpleX Chat. All rights reserved.</source> + <target>Telif Hakkı © 2024 SimpleX Chat. Tüm hakları saklıdır.</target> <note>Copyright (human-readable)</note> </trans-unit> </body> diff --git a/apps/ios/SimpleX Localizations/tr.xcloc/Source Contents/Shared/Assets.xcassets/AccentColor.colorset/Contents.json b/apps/ios/SimpleX Localizations/tr.xcloc/Source Contents/Shared/Assets.xcassets/AccentColor.colorset/Contents.json new file mode 100644 index 0000000000..aaa7f79bc8 --- /dev/null +++ b/apps/ios/SimpleX Localizations/tr.xcloc/Source Contents/Shared/Assets.xcassets/AccentColor.colorset/Contents.json @@ -0,0 +1,23 @@ +{ + "colors" : [ + { + "color" : { + "color-space" : "srgb", + "components" : { + "red" : "0.000", + "alpha" : "1.000", + "blue" : "1.000", + "green" : "0.533" + } + }, + "idiom" : "universal" + } + ], + "properties" : { + "localizable" : true + }, + "info" : { + "version" : 1, + "author" : "xcode" + } +} \ No newline at end of file diff --git a/apps/ios/SimpleX Localizations/tr.xcloc/Source Contents/Shared/Assets.xcassets/Contents.json b/apps/ios/SimpleX Localizations/tr.xcloc/Source Contents/Shared/Assets.xcassets/Contents.json new file mode 100644 index 0000000000..73c00596a7 --- /dev/null +++ b/apps/ios/SimpleX Localizations/tr.xcloc/Source Contents/Shared/Assets.xcassets/Contents.json @@ -0,0 +1,6 @@ +{ + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/apps/ios/SimpleX Localizations/tr.xcloc/Source Contents/SimpleX NSE/en.lproj/InfoPlist.strings b/apps/ios/SimpleX Localizations/tr.xcloc/Source Contents/SimpleX NSE/en.lproj/InfoPlist.strings new file mode 100644 index 0000000000..124ddbcc33 --- /dev/null +++ b/apps/ios/SimpleX Localizations/tr.xcloc/Source Contents/SimpleX NSE/en.lproj/InfoPlist.strings @@ -0,0 +1,6 @@ +/* Bundle display name */ +"CFBundleDisplayName" = "SimpleX NSE"; +/* Bundle name */ +"CFBundleName" = "SimpleX NSE"; +/* Copyright (human-readable) */ +"NSHumanReadableCopyright" = "Copyright © 2022 SimpleX Chat. All rights reserved."; diff --git a/apps/ios/SimpleX Localizations/tr.xcloc/Source Contents/en.lproj/Localizable.strings b/apps/ios/SimpleX Localizations/tr.xcloc/Source Contents/en.lproj/Localizable.strings new file mode 100644 index 0000000000..cf485752ea --- /dev/null +++ b/apps/ios/SimpleX Localizations/tr.xcloc/Source Contents/en.lproj/Localizable.strings @@ -0,0 +1,30 @@ +/* No comment provided by engineer. */ +"_italic_" = "\\_italic_"; + +/* No comment provided by engineer. */ +"**Add new contact**: to create your one-time QR Code for your contact." = "**Add new contact**: to create your one-time QR Code or link for your contact."; + +/* No comment provided by engineer. */ +"*bold*" = "\\*bold*"; + +/* No comment provided by engineer. */ +"`a + b`" = "\\`a + b`"; + +/* No comment provided by engineer. */ +"~strike~" = "\\~strike~"; + +/* call status */ +"connecting call" = "connecting call…"; + +/* No comment provided by engineer. */ +"Connecting server…" = "Connecting to server…"; + +/* No comment provided by engineer. */ +"Connecting server… (error: %@)" = "Connecting to server… (error: %@)"; + +/* rcv group event chat item */ +"member connected" = "connected"; + +/* No comment provided by engineer. */ +"No group!" = "Group not found!"; + diff --git a/apps/ios/SimpleX Localizations/tr.xcloc/Source Contents/en.lproj/SimpleX--iOS--InfoPlist.strings b/apps/ios/SimpleX Localizations/tr.xcloc/Source Contents/en.lproj/SimpleX--iOS--InfoPlist.strings new file mode 100644 index 0000000000..d34eb67fc7 --- /dev/null +++ b/apps/ios/SimpleX Localizations/tr.xcloc/Source Contents/en.lproj/SimpleX--iOS--InfoPlist.strings @@ -0,0 +1,12 @@ +/* Bundle name */ +"CFBundleName" = "SimpleX"; +/* Privacy - Camera Usage Description */ +"NSCameraUsageDescription" = "SimpleX needs camera access to scan QR codes to connect to other users and for video calls."; +/* Privacy - Face ID Usage Description */ +"NSFaceIDUsageDescription" = "SimpleX uses Face ID for local authentication"; +/* Privacy - Local Network Usage Description */ +"NSLocalNetworkUsageDescription" = "SimpleX uses local network access to allow using user chat profile via desktop app on the same network."; +/* Privacy - Microphone Usage Description */ +"NSMicrophoneUsageDescription" = "SimpleX needs microphone access for audio and video calls, and to record voice messages."; +/* Privacy - Photo Library Additions Usage Description */ +"NSPhotoLibraryAddUsageDescription" = "SimpleX needs access to Photo Library for saving captured and received media"; diff --git a/apps/ios/SimpleX Localizations/tr.xcloc/contents.json b/apps/ios/SimpleX Localizations/tr.xcloc/contents.json new file mode 100644 index 0000000000..0aee97a599 --- /dev/null +++ b/apps/ios/SimpleX Localizations/tr.xcloc/contents.json @@ -0,0 +1,12 @@ +{ + "developmentRegion" : "en", + "project" : "SimpleX.xcodeproj", + "targetLocale" : "tr", + "toolInfo" : { + "toolBuildNumber" : "15A240d", + "toolID" : "com.apple.dt.xcode", + "toolName" : "Xcode", + "toolVersion" : "15.0" + }, + "version" : "1.0" +} \ No newline at end of file diff --git a/apps/ios/SimpleX Localizations/uk.xcloc/Localized Contents/uk.xliff b/apps/ios/SimpleX Localizations/uk.xcloc/Localized Contents/uk.xliff index abd58231a9..566f97e546 100644 --- a/apps/ios/SimpleX Localizations/uk.xcloc/Localized Contents/uk.xliff +++ b/apps/ios/SimpleX Localizations/uk.xcloc/Localized Contents/uk.xliff @@ -89,6 +89,7 @@ </trans-unit> <trans-unit id="%@ and %@" xml:space="preserve"> <source>%@ and %@</source> + <target>%@ та %@</target> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="%@ and %@ connected" xml:space="preserve"> @@ -103,6 +104,7 @@ </trans-unit> <trans-unit id="%@ connected" xml:space="preserve"> <source>%@ connected</source> + <target>%@ підключено</target> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="%@ is connected!" xml:space="preserve"> @@ -132,6 +134,7 @@ </trans-unit> <trans-unit id="%@, %@ and %lld members" xml:space="preserve"> <source>%@, %@ and %lld members</source> + <target>%@, %@ та %lld учасників</target> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="%@, %@ and %lld other members connected" xml:space="preserve"> @@ -201,6 +204,7 @@ </trans-unit> <trans-unit id="%lld group events" xml:space="preserve"> <source>%lld group events</source> + <target>%lld групові заходи</target> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="%lld members" xml:space="preserve"> @@ -210,14 +214,21 @@ </trans-unit> <trans-unit id="%lld messages blocked" xml:space="preserve"> <source>%lld messages blocked</source> + <target>%lld повідомлень заблоковано</target> + <note>No comment provided by engineer.</note> + </trans-unit> + <trans-unit id="%lld messages blocked by admin" xml:space="preserve"> + <source>%lld messages blocked by admin</source> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="%lld messages marked deleted" xml:space="preserve"> <source>%lld messages marked deleted</source> + <target>%lld повідомлень позначено як видалені</target> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="%lld messages moderated by %@" xml:space="preserve"> <source>%lld messages moderated by %@</source> + <target>%lld повідомлень модерує %@</target> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="%lld minutes" xml:space="preserve"> @@ -227,6 +238,7 @@ </trans-unit> <trans-unit id="%lld new interface languages" xml:space="preserve"> <source>%lld new interface languages</source> + <target>%lld нові мови інтерфейсу</target> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="%lld second(s)" xml:space="preserve"> @@ -291,10 +303,12 @@ </trans-unit> <trans-unit id="(new)" xml:space="preserve"> <source>(new)</source> + <target>(новий)</target> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="(this device v%@)" xml:space="preserve"> <source>(this device v%@)</source> + <target>(цей пристрій v%@)</target> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id=")" xml:space="preserve"> @@ -302,14 +316,17 @@ <target>)</target> <note>No comment provided by engineer.</note> </trans-unit> + <trans-unit id="**Add contact**: to create a new invitation link, or connect via a link you received." xml:space="preserve"> + <source>**Add contact**: to create a new invitation link, or connect via a link you received.</source> + <note>No comment provided by engineer.</note> + </trans-unit> <trans-unit id="**Add new contact**: to create your one-time QR Code for your contact." xml:space="preserve"> <source>**Add new contact**: to create your one-time QR Code or link for your contact.</source> <target>**Додати новий контакт**: щоб створити одноразовий QR-код або посилання для свого контакту.</target> <note>No comment provided by engineer.</note> </trans-unit> - <trans-unit id="**Create link / QR code** for your contact to use." xml:space="preserve"> - <source>**Create link / QR code** for your contact to use.</source> - <target>**Створіть посилання / QR-код** для використання вашим контактом.</target> + <trans-unit id="**Create group**: to create a new group." xml:space="preserve"> + <source>**Create group**: to create a new group.</source> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="**More private**: check new messages every 20 minutes. Device token is shared with SimpleX Chat server, but not how many contacts or messages you have." xml:space="preserve"> @@ -322,11 +339,6 @@ <target>**Найбільш приватний**: не використовуйте сервер сповіщень SimpleX Chat, періодично перевіряйте повідомлення у фоновому режимі (залежить від того, як часто ви користуєтесь додатком).</target> <note>No comment provided by engineer.</note> </trans-unit> - <trans-unit id="**Paste received link** or open it in the browser and tap **Open in mobile app**." xml:space="preserve"> - <source>**Paste received link** or open it in the browser and tap **Open in mobile app**.</source> - <target>**Вставте отримане посилання** або відкрийте його в браузері і натисніть **Відкрити в мобільному додатку**.</target> - <note>No comment provided by engineer.</note> - </trans-unit> <trans-unit id="**Please note**: you will NOT be able to recover or change passphrase if you lose it." xml:space="preserve"> <source>**Please note**: you will NOT be able to recover or change passphrase if you lose it.</source> <target>**Зверніть увагу: ви НЕ зможете відновити або змінити пароль, якщо втратите його.</target> @@ -337,11 +349,6 @@ <target>**Рекомендується**: токен пристрою та сповіщення надсилаються на сервер сповіщень SimpleX Chat, але не вміст повідомлення, його розмір або від кого воно надійшло.</target> <note>No comment provided by engineer.</note> </trans-unit> - <trans-unit id="**Scan QR code**: to connect to your contact in person or via video call." xml:space="preserve"> - <source>**Scan QR code**: to connect to your contact in person or via video call.</source> - <target>**Відскануйте QR-код**: щоб з'єднатися з вашим контактом особисто або за допомогою відеодзвінка.</target> - <note>No comment provided by engineer.</note> - </trans-unit> <trans-unit id="**Warning**: Instant push notifications require passphrase saved in Keychain." xml:space="preserve"> <source>**Warning**: Instant push notifications require passphrase saved in Keychain.</source> <target>**Попередження**: Для отримання миттєвих пуш-сповіщень потрібна парольна фраза, збережена у брелоку.</target> @@ -371,6 +378,9 @@ <source>- connect to [directory service](simplex:/contact#/?v=1-4&smp=smp%3A%2F%2Fu2dS9sG8nMNURyZwqASV4yROM28Er0luVTx5X1CsMrU%3D%40smp4.simplex.im%2FeXSPwqTkKyDO3px4fLf1wx3MvPdjdLW3%23%2F%3Fv%3D1-2%26dh%3DMCowBQYDK2VuAyEAaiv6MkMH44L2TcYrt_CsX3ZvM11WgbMEUn0hkIKTOho%253D%26srv%3Do5vmywmrnaxalvz6wi3zicyftgio6psuvyniis6gco6bp6ekl4cqj4id.onion) (BETA)! - delivery receipts (up to 20 members). - faster and more stable.</source> + <target>- підключитися до [сервера каталогів](simplex:/contact#/?v=1-4&smp=smp%3A%2F%2Fu2dS9sG8nMNURyZwqASV4yROM28Er0luVTx5X1CsMrU%3D%40smp4.simplex.im%2FeXSPwqTkKyDO3px4fLf1wx3MvPdjdLW3%23%2F%3Fv%3D1-2%26dh%3DMCowBQYDK2VuAyEAaiv6MkMH44L2TcYrt_CsX3ZvM11WgbMEUn0hkIKTOho%253D%26srv%3Do5vmywmrnaxalvz6wi3zicyftgio6psuvyniis6gco6bp6ekl4cqj4id.onion) (БЕТА)! +- підтвердження доставлення (до 20 учасників). +- швидше і стабільніше.</target> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="- more stable message delivery. - a bit better groups. - and more!" xml:space="preserve"> @@ -386,6 +396,9 @@ <source>- optionally notify deleted contacts. - profile names with spaces. - and more!</source> + <target>- опція сповіщати про видалені контакти. +- імена профілів з пробілами. +- та багато іншого!</target> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="- voice messages up to 5 minutes. - custom time to disappear. - editing history." xml:space="preserve"> @@ -404,6 +417,7 @@ </trans-unit> <trans-unit id="0 sec" xml:space="preserve"> <source>0 sec</source> + <target>0 сек</target> <note>time to disappear</note> </trans-unit> <trans-unit id="0s" xml:space="preserve"> @@ -436,11 +450,6 @@ <target>1 тиждень</target> <note>time interval</note> </trans-unit> - <trans-unit id="1-time link" xml:space="preserve"> - <source>1-time link</source> - <target>1-разове посилання</target> - <note>No comment provided by engineer.</note> - </trans-unit> <trans-unit id="5 minutes" xml:space="preserve"> <source>5 minutes</source> <target>5 хвилин</target> @@ -556,6 +565,10 @@ <target>Додайте адресу до свого профілю, щоб ваші контакти могли поділитися нею з іншими людьми. Повідомлення про оновлення профілю буде надіслано вашим контактам.</target> <note>No comment provided by engineer.</note> </trans-unit> + <trans-unit id="Add contact" xml:space="preserve"> + <source>Add contact</source> + <note>No comment provided by engineer.</note> + </trans-unit> <trans-unit id="Add preset servers" xml:space="preserve"> <source>Add preset servers</source> <target>Додавання попередньо встановлених серверів</target> @@ -626,6 +639,10 @@ <target>Всі учасники групи залишаться на зв'язку.</target> <note>No comment provided by engineer.</note> </trans-unit> + <trans-unit id="All messages will be deleted - this cannot be undone!" xml:space="preserve"> + <source>All messages will be deleted - this cannot be undone!</source> + <note>No comment provided by engineer.</note> + </trans-unit> <trans-unit id="All messages will be deleted - this cannot be undone! The messages will be deleted ONLY for you." xml:space="preserve"> <source>All messages will be deleted - this cannot be undone! The messages will be deleted ONLY for you.</source> <target>Всі повідомлення будуть видалені - це неможливо скасувати! Повідомлення будуть видалені ТІЛЬКИ для вас.</target> @@ -633,6 +650,7 @@ </trans-unit> <trans-unit id="All new messages from %@ will be hidden!" xml:space="preserve"> <source>All new messages from %@ will be hidden!</source> + <target>Всі нові повідомлення від %@ будуть приховані!</target> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="All your contacts will remain connected." xml:space="preserve"> @@ -660,9 +678,9 @@ <target>Дозволяйте зникати повідомленням, тільки якщо контакт дозволяє вам це робити.</target> <note>No comment provided by engineer.</note> </trans-unit> - <trans-unit id="Allow irreversible message deletion only if your contact allows it to you." xml:space="preserve"> - <source>Allow irreversible message deletion only if your contact allows it to you.</source> - <target>Дозволяйте безповоротне видалення повідомлень, тільки якщо контакт дозволяє вам це зробити.</target> + <trans-unit id="Allow irreversible message deletion only if your contact allows it to you. (24 hours)" xml:space="preserve"> + <source>Allow irreversible message deletion only if your contact allows it to you. (24 hours)</source> + <target>Дозволяйте безповоротне видалення повідомлень, тільки якщо контакт дозволяє вам це зробити. (24 години)</target> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="Allow message reactions only if your contact allows them." xml:space="preserve"> @@ -685,9 +703,9 @@ <target>Дозволити надсилання зникаючих повідомлень.</target> <note>No comment provided by engineer.</note> </trans-unit> - <trans-unit id="Allow to irreversibly delete sent messages." xml:space="preserve"> - <source>Allow to irreversibly delete sent messages.</source> - <target>Дозволяє безповоротно видаляти надіслані повідомлення.</target> + <trans-unit id="Allow to irreversibly delete sent messages. (24 hours)" xml:space="preserve"> + <source>Allow to irreversibly delete sent messages. (24 hours)</source> + <target>Дозволяє безповоротно видаляти надіслані повідомлення. (24 години)</target> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="Allow to send files and media." xml:space="preserve"> @@ -720,9 +738,9 @@ <target>Дозвольте вашим контактам телефонувати вам.</target> <note>No comment provided by engineer.</note> </trans-unit> - <trans-unit id="Allow your contacts to irreversibly delete sent messages." xml:space="preserve"> - <source>Allow your contacts to irreversibly delete sent messages.</source> - <target>Дозвольте вашим контактам безповоротно видаляти надіслані повідомлення.</target> + <trans-unit id="Allow your contacts to irreversibly delete sent messages. (24 hours)" xml:space="preserve"> + <source>Allow your contacts to irreversibly delete sent messages. (24 hours)</source> + <target>Дозвольте вашим контактам безповоротно видаляти надіслані повідомлення. (24 години)</target> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="Allow your contacts to send disappearing messages." xml:space="preserve"> @@ -742,10 +760,12 @@ </trans-unit> <trans-unit id="Already connecting!" xml:space="preserve"> <source>Already connecting!</source> + <target>Вже підключаємось!</target> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="Already joining the group!" xml:space="preserve"> <source>Already joining the group!</source> + <target>Вже приєднуємося до групи!</target> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="Always use relay" xml:space="preserve"> @@ -770,6 +790,7 @@ </trans-unit> <trans-unit id="App encrypts new local files (except videos)." xml:space="preserve"> <source>App encrypts new local files (except videos).</source> + <target>Додаток шифрує нові локальні файли (крім відео).</target> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="App icon" xml:space="preserve"> @@ -869,6 +890,7 @@ </trans-unit> <trans-unit id="Bad desktop address" xml:space="preserve"> <source>Bad desktop address</source> + <target>Неправильна адреса робочого столу</target> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="Bad message ID" xml:space="preserve"> @@ -883,6 +905,7 @@ </trans-unit> <trans-unit id="Better groups" xml:space="preserve"> <source>Better groups</source> + <target>Кращі групи</target> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="Better messages" xml:space="preserve"> @@ -892,18 +915,34 @@ </trans-unit> <trans-unit id="Block" xml:space="preserve"> <source>Block</source> + <target>Блокувати</target> + <note>No comment provided by engineer.</note> + </trans-unit> + <trans-unit id="Block for all" xml:space="preserve"> + <source>Block for all</source> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="Block group members" xml:space="preserve"> <source>Block group members</source> + <target>Учасники групи блокування</target> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="Block member" xml:space="preserve"> <source>Block member</source> + <target>Заблокувати користувача</target> + <note>No comment provided by engineer.</note> + </trans-unit> + <trans-unit id="Block member for all?" xml:space="preserve"> + <source>Block member for all?</source> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="Block member?" xml:space="preserve"> <source>Block member?</source> + <target>Заблокувати користувача?</target> + <note>No comment provided by engineer.</note> + </trans-unit> + <trans-unit id="Blocked by admin" xml:space="preserve"> + <source>Blocked by admin</source> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="Both you and your contact can add message reactions." xml:space="preserve"> @@ -911,9 +950,9 @@ <target>Реакції на повідомлення можете додавати як ви, так і ваш контакт.</target> <note>No comment provided by engineer.</note> </trans-unit> - <trans-unit id="Both you and your contact can irreversibly delete sent messages." xml:space="preserve"> - <source>Both you and your contact can irreversibly delete sent messages.</source> - <target>І ви, і ваш контакт можете безповоротно видалити надіслані повідомлення.</target> + <trans-unit id="Both you and your contact can irreversibly delete sent messages. (24 hours)" xml:space="preserve"> + <source>Both you and your contact can irreversibly delete sent messages. (24 hours)</source> + <target>І ви, і ваш контакт можете безповоротно видалити надіслані повідомлення. (24 години)</target> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="Both you and your contact can make calls." xml:space="preserve"> @@ -933,6 +972,7 @@ </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"> <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>Болгарською, фінською, тайською та українською мовами - завдяки користувачам та [Weblate](https://github.com/simplex-chat/simplex-chat/tree/stable#help-translating-simplex-chat)!</target> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="By chat profile (default) or [by connection](https://simplex.chat/blog/20230204-simplex-chat-v4-5-user-chat-profiles.html#transport-isolation) (BETA)." xml:space="preserve"> @@ -950,9 +990,8 @@ <target>Дзвінки</target> <note>No comment provided by engineer.</note> </trans-unit> - <trans-unit id="Can't delete user profile!" xml:space="preserve"> - <source>Can't delete user profile!</source> - <target>Не можу видалити профіль користувача!</target> + <trans-unit id="Camera not available" xml:space="preserve"> + <source>Camera not available</source> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="Can't invite contact!" xml:space="preserve"> @@ -1066,6 +1105,10 @@ <target>Чат зупинено</target> <note>No comment provided by engineer.</note> </trans-unit> + <trans-unit id="Chat is stopped. If you already used this database on another device, you should transfer it back before starting chat." xml:space="preserve"> + <source>Chat is stopped. If you already used this database on another device, you should transfer it back before starting chat.</source> + <note>No comment provided by engineer.</note> + </trans-unit> <trans-unit id="Chat preferences" xml:space="preserve"> <source>Chat preferences</source> <target>Налаштування чату</target> @@ -1111,6 +1154,10 @@ <target>Відверта розмова?</target> <note>No comment provided by engineer.</note> </trans-unit> + <trans-unit id="Clear private notes?" xml:space="preserve"> + <source>Clear private notes?</source> + <note>No comment provided by engineer.</note> + </trans-unit> <trans-unit id="Clear verification" xml:space="preserve"> <source>Clear verification</source> <target>Очистити перевірку</target> @@ -1168,6 +1215,7 @@ </trans-unit> <trans-unit id="Connect automatically" xml:space="preserve"> <source>Connect automatically</source> + <target>Підключення автоматично</target> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="Connect incognito" xml:space="preserve"> @@ -1177,24 +1225,31 @@ </trans-unit> <trans-unit id="Connect to desktop" xml:space="preserve"> <source>Connect to desktop</source> + <target>Підключення до комп'ютера</target> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="Connect to yourself?" xml:space="preserve"> <source>Connect to yourself?</source> + <target>З'єднатися з самим собою?</target> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="Connect to yourself? This is your own SimpleX address!" xml:space="preserve"> <source>Connect to yourself? This is your own SimpleX address!</source> + <target>З'єднатися з самим собою? +Це ваша власна SimpleX-адреса!</target> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="Connect to yourself? This is your own one-time link!" xml:space="preserve"> <source>Connect to yourself? This is your own one-time link!</source> + <target>Підключитися до себе? +Це ваше власне одноразове посилання!</target> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="Connect via contact address" xml:space="preserve"> <source>Connect via contact address</source> + <target>Підключіться за контактною адресою</target> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="Connect via link" xml:space="preserve"> @@ -1202,11 +1257,6 @@ This is your own one-time link!</source> <target>Підключіться за посиланням</target> <note>No comment provided by engineer.</note> </trans-unit> - <trans-unit id="Connect via link / QR code" xml:space="preserve"> - <source>Connect via link / QR code</source> - <target>Підключитися за посиланням / QR-кодом</target> - <note>No comment provided by engineer.</note> - </trans-unit> <trans-unit id="Connect via one-time link" xml:space="preserve"> <source>Connect via one-time link</source> <target>Під'єднатися за одноразовим посиланням</target> @@ -1214,10 +1264,12 @@ This is your own one-time link!</source> </trans-unit> <trans-unit id="Connect with %@" xml:space="preserve"> <source>Connect with %@</source> + <target>Підключитися до %@</target> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="Connected desktop" xml:space="preserve"> <source>Connected desktop</source> + <target>Підключений робочий стіл</target> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="Connected to desktop" xml:space="preserve"> @@ -1373,11 +1425,6 @@ This is your own one-time link!</source> <source>Create new profile in [desktop app](https://simplex.chat/downloads/). 💻</source> <note>No comment provided by engineer.</note> </trans-unit> - <trans-unit id="Create one-time invitation link" xml:space="preserve"> - <source>Create one-time invitation link</source> - <target>Створіть одноразове посилання-запрошення</target> - <note>No comment provided by engineer.</note> - </trans-unit> <trans-unit id="Create profile" xml:space="preserve"> <source>Create profile</source> <note>No comment provided by engineer.</note> @@ -1397,11 +1444,23 @@ This is your own one-time link!</source> <target>Створіть свій профіль</target> <note>No comment provided by engineer.</note> </trans-unit> + <trans-unit id="Created at" xml:space="preserve"> + <source>Created at</source> + <note>No comment provided by engineer.</note> + </trans-unit> + <trans-unit id="Created at: %@" xml:space="preserve"> + <source>Created at: %@</source> + <note>copied message info</note> + </trans-unit> <trans-unit id="Created on %@" xml:space="preserve"> <source>Created on %@</source> <target>Створено %@</target> <note>No comment provided by engineer.</note> </trans-unit> + <trans-unit id="Creating link…" xml:space="preserve"> + <source>Creating link…</source> + <note>No comment provided by engineer.</note> + </trans-unit> <trans-unit id="Current Passcode" xml:space="preserve"> <source>Current Passcode</source> <target>Поточний пароль</target> @@ -1872,6 +1931,10 @@ This cannot be undone!</source> <target>Зробіть це пізніше</target> <note>No comment provided by engineer.</note> </trans-unit> + <trans-unit id="Do not send history to new members." xml:space="preserve"> + <source>Do not send history to new members.</source> + <note>No comment provided by engineer.</note> + </trans-unit> <trans-unit id="Don't create address" xml:space="preserve"> <source>Don't create address</source> <target>Не створювати адресу</target> @@ -1942,6 +2005,10 @@ This cannot be undone!</source> <target>Увімкнути автоматичне видалення повідомлень?</target> <note>No comment provided by engineer.</note> </trans-unit> + <trans-unit id="Enable camera access" xml:space="preserve"> + <source>Enable camera access</source> + <note>No comment provided by engineer.</note> + </trans-unit> <trans-unit id="Enable for all" xml:space="preserve"> <source>Enable for all</source> <target>Увімкнути для всіх</target> @@ -2005,6 +2072,10 @@ This cannot be undone!</source> <target>Зашифроване повідомлення або інша подія</target> <note>notification</note> </trans-unit> + <trans-unit id="Encrypted message: app is stopped" xml:space="preserve"> + <source>Encrypted message: app is stopped</source> + <note>notification</note> + </trans-unit> <trans-unit id="Encrypted message: database error" xml:space="preserve"> <source>Encrypted message: database error</source> <target>Зашифроване повідомлення: помилка бази даних</target> @@ -2144,6 +2215,10 @@ This cannot be undone!</source> <source>Error creating member contact</source> <note>No comment provided by engineer.</note> </trans-unit> + <trans-unit id="Error creating message" xml:space="preserve"> + <source>Error creating message</source> + <note>No comment provided by engineer.</note> + </trans-unit> <trans-unit id="Error creating profile!" xml:space="preserve"> <source>Error creating profile!</source> <target>Помилка створення профілю!</target> @@ -2228,6 +2303,10 @@ This cannot be undone!</source> <target>Помилка завантаження %@ серверів</target> <note>No comment provided by engineer.</note> </trans-unit> + <trans-unit id="Error opening chat" xml:space="preserve"> + <source>Error opening chat</source> + <note>No comment provided by engineer.</note> + </trans-unit> <trans-unit id="Error receiving file" xml:space="preserve"> <source>Error receiving file</source> <target>Помилка отримання файлу</target> @@ -2268,6 +2347,10 @@ This cannot be undone!</source> <target>Помилка збереження пароля користувача</target> <note>No comment provided by engineer.</note> </trans-unit> + <trans-unit id="Error scanning code: %@" xml:space="preserve"> + <source>Error scanning code: %@</source> + <note>No comment provided by engineer.</note> + </trans-unit> <trans-unit id="Error sending email" xml:space="preserve"> <source>Error sending email</source> <target>Помилка надсилання електронного листа</target> @@ -2591,9 +2674,9 @@ This cannot be undone!</source> <target>Учасники групи можуть додавати реакції на повідомлення.</target> <note>No comment provided by engineer.</note> </trans-unit> - <trans-unit id="Group members can irreversibly delete sent messages." xml:space="preserve"> - <source>Group members can irreversibly delete sent messages.</source> - <target>Учасники групи можуть безповоротно видаляти надіслані повідомлення.</target> + <trans-unit id="Group members can irreversibly delete sent messages. (24 hours)" xml:space="preserve"> + <source>Group members can irreversibly delete sent messages. (24 hours)</source> + <target>Учасники групи можуть безповоротно видаляти надіслані повідомлення. (24 години)</target> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="Group members can send direct messages." xml:space="preserve"> @@ -2701,6 +2784,10 @@ This cannot be undone!</source> <target>Історія</target> <note>No comment provided by engineer.</note> </trans-unit> + <trans-unit id="History is not sent to new members." xml:space="preserve"> + <source>History is not sent to new members.</source> + <note>No comment provided by engineer.</note> + </trans-unit> <trans-unit id="How SimpleX works" xml:space="preserve"> <source>How SimpleX works</source> <target>Як працює SimpleX</target> @@ -2736,11 +2823,6 @@ This cannot be undone!</source> <target>Якщо ви не можете зустрітися особисто, покажіть QR-код у відеодзвінку або поділіться посиланням.</target> <note>No comment provided by engineer.</note> </trans-unit> - <trans-unit id="If you cannot meet in person, you can **scan QR code in the video call**, or your contact can share an invitation link." xml:space="preserve"> - <source>If you cannot meet in person, you can **scan QR code in the video call**, or your contact can share an invitation link.</source> - <target>Якщо ви не можете зустрітися особисто, ви можете **сканувати QR-код у відеодзвінку**, або ваш контакт може поділитися посиланням на запрошення.</target> - <note>No comment provided by engineer.</note> - </trans-unit> <trans-unit id="If you enter this passcode when opening the app, all app data will be irreversibly removed!" xml:space="preserve"> <source>If you enter this passcode when opening the app, all app data will be irreversibly removed!</source> <target>Якщо ви введете цей пароль при відкритті програми, всі дані програми будуть безповоротно видалені!</target> @@ -2796,6 +2878,10 @@ This cannot be undone!</source> <target>Імпорт бази даних</target> <note>No comment provided by engineer.</note> </trans-unit> + <trans-unit id="Improved message delivery" xml:space="preserve"> + <source>Improved message delivery</source> + <note>No comment provided by engineer.</note> + </trans-unit> <trans-unit id="Improved privacy and security" xml:space="preserve"> <source>Improved privacy and security</source> <target>Покращена конфіденційність та безпека</target> @@ -2896,15 +2982,31 @@ This cannot be undone!</source> <target>Інтерфейс</target> <note>No comment provided by engineer.</note> </trans-unit> + <trans-unit id="Invalid QR code" xml:space="preserve"> + <source>Invalid QR code</source> + <note>No comment provided by engineer.</note> + </trans-unit> <trans-unit id="Invalid connection link" xml:space="preserve"> <source>Invalid connection link</source> <target>Неправильне посилання для підключення</target> <note>No comment provided by engineer.</note> </trans-unit> + <trans-unit id="Invalid display name!" xml:space="preserve"> + <source>Invalid display name!</source> + <note>No comment provided by engineer.</note> + </trans-unit> + <trans-unit id="Invalid link" xml:space="preserve"> + <source>Invalid link</source> + <note>No comment provided by engineer.</note> + </trans-unit> <trans-unit id="Invalid name!" xml:space="preserve"> <source>Invalid name!</source> <note>No comment provided by engineer.</note> </trans-unit> + <trans-unit id="Invalid response" xml:space="preserve"> + <source>Invalid response</source> + <note>No comment provided by engineer.</note> + </trans-unit> <trans-unit id="Invalid server address!" xml:space="preserve"> <source>Invalid server address!</source> <target>Неправильна адреса сервера!</target> @@ -2996,6 +3098,10 @@ This cannot be undone!</source> <target>Приєднуйтесь до групи</target> <note>No comment provided by engineer.</note> </trans-unit> + <trans-unit id="Join group conversations" xml:space="preserve"> + <source>Join group conversations</source> + <note>No comment provided by engineer.</note> + </trans-unit> <trans-unit id="Join group?" xml:space="preserve"> <source>Join group?</source> <note>No comment provided by engineer.</note> @@ -3019,10 +3125,18 @@ This is your link for group %@!</source> <target>Приєднання до групи</target> <note>No comment provided by engineer.</note> </trans-unit> + <trans-unit id="Keep" xml:space="preserve"> + <source>Keep</source> + <note>No comment provided by engineer.</note> + </trans-unit> <trans-unit id="Keep the app open to use it from desktop" xml:space="preserve"> <source>Keep the app open to use it from desktop</source> <note>No comment provided by engineer.</note> </trans-unit> + <trans-unit id="Keep unused invitation?" xml:space="preserve"> + <source>Keep unused invitation?</source> + <note>No comment provided by engineer.</note> + </trans-unit> <trans-unit id="Keep your connections" xml:space="preserve"> <source>Keep your connections</source> <target>Зберігайте свої зв'язки</target> @@ -3105,6 +3219,11 @@ This is your link for group %@!</source> <target>Живі повідомлення</target> <note>No comment provided by engineer.</note> </trans-unit> + <trans-unit id="Local" xml:space="preserve"> + <source>Local</source> + <target>Локально</target> + <note>No comment provided by engineer.</note> + </trans-unit> <trans-unit id="Local name" xml:space="preserve"> <source>Local name</source> <target>Місцева назва</target> @@ -3344,6 +3463,10 @@ This is your link for group %@!</source> <target>Новий пароль</target> <note>No comment provided by engineer.</note> </trans-unit> + <trans-unit id="New chat" xml:space="preserve"> + <source>New chat</source> + <note>No comment provided by engineer.</note> + </trans-unit> <trans-unit id="New contact request" xml:space="preserve"> <source>New contact request</source> <target>Новий запит на контакт</target> @@ -3466,16 +3589,15 @@ This is your link for group %@!</source> - відключати користувачів (роль "спостерігач")</target> <note>No comment provided by engineer.</note> </trans-unit> + <trans-unit id="OK" xml:space="preserve"> + <source>OK</source> + <note>No comment provided by engineer.</note> + </trans-unit> <trans-unit id="Off" xml:space="preserve"> <source>Off</source> <target>Вимкнено</target> <note>No comment provided by engineer.</note> </trans-unit> - <trans-unit id="Off (Local)" xml:space="preserve"> - <source>Off (Local)</source> - <target>Вимкнено (локально)</target> - <note>No comment provided by engineer.</note> - </trans-unit> <trans-unit id="Ok" xml:space="preserve"> <source>Ok</source> <target>Гаразд</target> @@ -3536,9 +3658,9 @@ This is your link for group %@!</source> <target>Тільки ви можете додавати реакції на повідомлення.</target> <note>No comment provided by engineer.</note> </trans-unit> - <trans-unit id="Only you can irreversibly delete messages (your contact can mark them for deletion)." xml:space="preserve"> - <source>Only you can irreversibly delete messages (your contact can mark them for deletion).</source> - <target>Тільки ви можете безповоротно видалити повідомлення (ваш контакт може позначити їх для видалення).</target> + <trans-unit id="Only you can irreversibly delete messages (your contact can mark them for deletion). (24 hours)" xml:space="preserve"> + <source>Only you can irreversibly delete messages (your contact can mark them for deletion). (24 hours)</source> + <target>Тільки ви можете безповоротно видалити повідомлення (ваш контакт може позначити їх для видалення). (24 години)</target> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="Only you can make calls." xml:space="preserve"> @@ -3561,9 +3683,9 @@ This is your link for group %@!</source> <target>Тільки ваш контакт може додавати реакції на повідомлення.</target> <note>No comment provided by engineer.</note> </trans-unit> - <trans-unit id="Only your contact can irreversibly delete messages (you can mark them for deletion)." xml:space="preserve"> - <source>Only your contact can irreversibly delete messages (you can mark them for deletion).</source> - <target>Тільки ваш контакт може безповоротно видалити повідомлення (ви можете позначити їх для видалення).</target> + <trans-unit id="Only your contact can irreversibly delete messages (you can mark them for deletion). (24 hours)" xml:space="preserve"> + <source>Only your contact can irreversibly delete messages (you can mark them for deletion). (24 hours)</source> + <target>Тільки ваш контакт може безповоротно видалити повідомлення (ви можете позначити їх для видалення). (24 години)</target> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="Only your contact can make calls." xml:space="preserve"> @@ -3614,9 +3736,16 @@ This is your link for group %@!</source> <target>Протокол і код з відкритим вихідним кодом - будь-хто може запускати сервери.</target> <note>No comment provided by engineer.</note> </trans-unit> - <trans-unit id="Opening database…" xml:space="preserve"> - <source>Opening database…</source> - <target>Відкриття бази даних…</target> + <trans-unit id="Opening app…" xml:space="preserve"> + <source>Opening app…</source> + <note>No comment provided by engineer.</note> + </trans-unit> + <trans-unit id="Or scan QR code" xml:space="preserve"> + <source>Or scan QR code</source> + <note>No comment provided by engineer.</note> + </trans-unit> + <trans-unit id="Or show this code" xml:space="preserve"> + <source>Or show this code</source> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="PING count" xml:space="preserve"> @@ -3659,10 +3788,9 @@ This is your link for group %@!</source> <target>Показати пароль</target> <note>No comment provided by engineer.</note> </trans-unit> - <trans-unit id="Paste" xml:space="preserve"> - <source>Paste</source> - <target>Вставити</target> - <note>No comment provided by engineer.</note> + <trans-unit id="Past member %@" xml:space="preserve"> + <source>Past member %@</source> + <note>past/unknown group member</note> </trans-unit> <trans-unit id="Paste desktop address" xml:space="preserve"> <source>Paste desktop address</source> @@ -3673,15 +3801,13 @@ This is your link for group %@!</source> <target>Вставити зображення</target> <note>No comment provided by engineer.</note> </trans-unit> - <trans-unit id="Paste received link" xml:space="preserve"> - <source>Paste received link</source> - <target>Вставте отримане посилання</target> + <trans-unit id="Paste link to connect!" xml:space="preserve"> + <source>Paste link to connect!</source> <note>No comment provided by engineer.</note> </trans-unit> - <trans-unit id="Paste the link you received to connect with your contact." xml:space="preserve"> - <source>Paste the link you received to connect with your contact.</source> - <target>Вставте отримане посилання для зв'язку з вашим контактом.</target> - <note>placeholder</note> + <trans-unit id="Paste the link you received" xml:space="preserve"> + <source>Paste the link you received</source> + <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="People can connect to you only via the links you share." xml:space="preserve"> <source>People can connect to you only via the links you share.</source> @@ -3718,6 +3844,11 @@ This is your link for group %@!</source> <target>Будь ласка, перевірте свої та контактні налаштування.</target> <note>No comment provided by engineer.</note> </trans-unit> + <trans-unit id="Please contact developers. Error: %@" xml:space="preserve"> + <source>Please contact developers. +Error: %@</source> + <note>No comment provided by engineer.</note> + </trans-unit> <trans-unit id="Please contact group admin." xml:space="preserve"> <source>Please contact group admin.</source> <target>Зверніться до адміністратора групи.</target> @@ -3803,6 +3934,10 @@ This is your link for group %@!</source> <target>Приватні імена файлів</target> <note>No comment provided by engineer.</note> </trans-unit> + <trans-unit id="Private notes" xml:space="preserve"> + <source>Private notes</source> + <note>name of notes to self</note> + </trans-unit> <trans-unit id="Profile and server connections" xml:space="preserve"> <source>Profile and server connections</source> <target>З'єднання профілю та сервера</target> @@ -3921,6 +4056,10 @@ This is your link for group %@!</source> <target>Читайте більше в [Посібнику користувача](https://simplex.chat/docs/guide/app-settings.html#your-simplex-contact-address).</target> <note>No comment provided by engineer.</note> </trans-unit> + <trans-unit id="Read more in [User Guide](https://simplex.chat/docs/guide/chat-profiles.html#incognito-mode)." xml:space="preserve"> + <source>Read more in [User Guide](https://simplex.chat/docs/guide/chat-profiles.html#incognito-mode).</source> + <note>No comment provided by engineer.</note> + </trans-unit> <trans-unit id="Read more in [User Guide](https://simplex.chat/docs/guide/readme.html#connect-to-friends)." xml:space="preserve"> <source>Read more in [User Guide](https://simplex.chat/docs/guide/readme.html#connect-to-friends).</source> <target>Читайте більше в [Посібнику користувача](https://simplex.chat/docs/guide/readme.html#connect-to-friends).</target> @@ -3976,6 +4115,10 @@ This is your link for group %@!</source> <target>Отримання через</target> <note>No comment provided by engineer.</note> </trans-unit> + <trans-unit id="Recent history and improved [directory bot](simplex:/contact#/?v=1-4&smp=smp%3A%2F%2Fu2dS9sG8nMNURyZwqASV4yROM28Er0luVTx5X1CsMrU%3D%40smp4.simplex.im%2FeXSPwqTkKyDO3px4fLf1wx3MvPdjdLW3%23%2F%3Fv%3D1-2%26dh%3DMCowBQYDK2VuAyEAaiv6MkMH44L2TcYrt_CsX3ZvM11WgbMEUn0hkIKTOho%253D%26srv%3Do5vmywmrnaxalvz6wi3zicyftgio6psuvyniis6gco6bp6ekl4cqj4id.onion)." xml:space="preserve"> + <source>Recent history and improved [directory bot](simplex:/contact#/?v=1-4&smp=smp%3A%2F%2Fu2dS9sG8nMNURyZwqASV4yROM28Er0luVTx5X1CsMrU%3D%40smp4.simplex.im%2FeXSPwqTkKyDO3px4fLf1wx3MvPdjdLW3%23%2F%3Fv%3D1-2%26dh%3DMCowBQYDK2VuAyEAaiv6MkMH44L2TcYrt_CsX3ZvM11WgbMEUn0hkIKTOho%253D%26srv%3Do5vmywmrnaxalvz6wi3zicyftgio6psuvyniis6gco6bp6ekl4cqj4id.onion).</source> + <note>No comment provided by engineer.</note> + </trans-unit> <trans-unit id="Recipients see updates as you type them." xml:space="preserve"> <source>Recipients see updates as you type them.</source> <target>Одержувачі бачать оновлення, коли ви їх вводите.</target> @@ -4129,6 +4272,10 @@ This is your link for group %@!</source> <target>Відновлення помилки бази даних</target> <note>No comment provided by engineer.</note> </trans-unit> + <trans-unit id="Retry" xml:space="preserve"> + <source>Retry</source> + <note>No comment provided by engineer.</note> + </trans-unit> <trans-unit id="Reveal" xml:space="preserve"> <source>Reveal</source> <target>Показувати</target> @@ -4254,6 +4401,10 @@ This is your link for group %@!</source> <target>Збережені сервери WebRTC ICE буде видалено</target> <note>No comment provided by engineer.</note> </trans-unit> + <trans-unit id="Saved message" xml:space="preserve"> + <source>Saved message</source> + <note>message info title</note> + </trans-unit> <trans-unit id="Scan QR code" xml:space="preserve"> <source>Scan QR code</source> <target>Відскануйте QR-код</target> @@ -4283,6 +4434,14 @@ This is your link for group %@!</source> <target>Пошук</target> <note>No comment provided by engineer.</note> </trans-unit> + <trans-unit id="Search bar accepts invitation links." xml:space="preserve"> + <source>Search bar accepts invitation links.</source> + <note>No comment provided by engineer.</note> + </trans-unit> + <trans-unit id="Search or paste SimpleX link" xml:space="preserve"> + <source>Search or paste SimpleX link</source> + <note>No comment provided by engineer.</note> + </trans-unit> <trans-unit id="Secure queue" xml:space="preserve"> <source>Secure queue</source> <target>Безпечна черга</target> @@ -4387,6 +4546,10 @@ This is your link for group %@!</source> <target>Надсилайте їх із галереї чи власних клавіатур.</target> <note>No comment provided by engineer.</note> </trans-unit> + <trans-unit id="Send up to 100 last messages to new members." xml:space="preserve"> + <source>Send up to 100 last messages to new members.</source> + <note>No comment provided by engineer.</note> + </trans-unit> <trans-unit id="Sender cancelled file transfer." xml:space="preserve"> <source>Sender cancelled file transfer.</source> <target>Відправник скасував передачу файлу.</target> @@ -4556,9 +4719,8 @@ This is your link for group %@!</source> <target>Поділіться посиланням</target> <note>No comment provided by engineer.</note> </trans-unit> - <trans-unit id="Share one-time invitation link" xml:space="preserve"> - <source>Share one-time invitation link</source> - <target>Поділіться посиланням на одноразове запрошення</target> + <trans-unit id="Share this 1-time invite link" xml:space="preserve"> + <source>Share this 1-time invite link</source> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="Share with contacts" xml:space="preserve"> @@ -4680,16 +4842,15 @@ This is your link for group %@!</source> <target>Хтось</target> <note>notification title</note> </trans-unit> - <trans-unit id="Start a new chat" xml:space="preserve"> - <source>Start a new chat</source> - <target>Почніть новий чат</target> - <note>No comment provided by engineer.</note> - </trans-unit> <trans-unit id="Start chat" xml:space="preserve"> <source>Start chat</source> <target>Почати чат</target> <note>No comment provided by engineer.</note> </trans-unit> + <trans-unit id="Start chat?" xml:space="preserve"> + <source>Start chat?</source> + <note>No comment provided by engineer.</note> + </trans-unit> <trans-unit id="Start migration" xml:space="preserve"> <source>Start migration</source> <target>Почати міграцію</target> @@ -4814,6 +4975,14 @@ This is your link for group %@!</source> <target>Натисніть, щоб приєднатися інкогніто</target> <note>No comment provided by engineer.</note> </trans-unit> + <trans-unit id="Tap to paste link" xml:space="preserve"> + <source>Tap to paste link</source> + <note>No comment provided by engineer.</note> + </trans-unit> + <trans-unit id="Tap to scan" xml:space="preserve"> + <source>Tap to scan</source> + <note>No comment provided by engineer.</note> + </trans-unit> <trans-unit id="Tap to start a new chat" xml:space="preserve"> <source>Tap to start a new chat</source> <target>Натисніть, щоб почати новий чат</target> @@ -4876,6 +5045,10 @@ It can happen because of some bug or when the connection is compromised.</source <target>Спроба змінити пароль до бази даних не була завершена.</target> <note>No comment provided by engineer.</note> </trans-unit> + <trans-unit id="The code you scanned is not a SimpleX link QR code." xml:space="preserve"> + <source>The code you scanned is not a SimpleX link QR code.</source> + <note>No comment provided by engineer.</note> + </trans-unit> <trans-unit id="The connection you accepted will be cancelled!" xml:space="preserve"> <source>The connection you accepted will be cancelled!</source> <target>Прийняте вами з'єднання буде скасовано!</target> @@ -4941,21 +5114,15 @@ It can happen because of some bug or when the connection is compromised.</source <target>Сервери для нових підключень вашого поточного профілю чату **%@**.</target> <note>No comment provided by engineer.</note> </trans-unit> + <trans-unit id="The text you pasted is not a SimpleX link." xml:space="preserve"> + <source>The text you pasted is not a SimpleX link.</source> + <note>No comment provided by engineer.</note> + </trans-unit> <trans-unit id="Theme" xml:space="preserve"> <source>Theme</source> <target>Тема</target> <note>No comment provided by engineer.</note> </trans-unit> - <trans-unit id="There should be at least one user profile." xml:space="preserve"> - <source>There should be at least one user profile.</source> - <target>Повинен бути принаймні один профіль користувача.</target> - <note>No comment provided by engineer.</note> - </trans-unit> - <trans-unit id="There should be at least one visible user profile." xml:space="preserve"> - <source>There should be at least one visible user profile.</source> - <target>Повинен бути принаймні один видимий профіль користувача.</target> - <note>No comment provided by engineer.</note> - </trans-unit> <trans-unit id="These settings are for your current profile **%@**." xml:space="preserve"> <source>These settings are for your current profile **%@**.</source> <target>Ці налаштування стосуються вашого поточного профілю **%@**.</target> @@ -4985,6 +5152,10 @@ It can happen because of some bug or when the connection is compromised.</source <source>This device name</source> <note>No comment provided by engineer.</note> </trans-unit> + <trans-unit id="This display name is invalid. Please choose another name." xml:space="preserve"> + <source>This display name is invalid. Please choose another name.</source> + <note>No comment provided by engineer.</note> + </trans-unit> <trans-unit id="This group has over %lld members, delivery receipts are not sent." xml:space="preserve"> <source>This group has over %lld members, delivery receipts are not sent.</source> <target>У цій групі більше %lld учасників, підтвердження доставки не надсилаються.</target> @@ -5083,16 +5254,15 @@ You will be prompted to complete authentication before this feature is enabled.< <target>Спроба з'єднатися з сервером, який використовується для отримання повідомлень від цього контакту.</target> <note>No comment provided by engineer.</note> </trans-unit> + <trans-unit id="Turkish interface" xml:space="preserve"> + <source>Turkish interface</source> + <note>No comment provided by engineer.</note> + </trans-unit> <trans-unit id="Turn off" xml:space="preserve"> <source>Turn off</source> <target>Вимкнути</target> <note>No comment provided by engineer.</note> </trans-unit> - <trans-unit id="Turn off notifications?" xml:space="preserve"> - <source>Turn off notifications?</source> - <target>Вимкнути сповіщення?</target> - <note>No comment provided by engineer.</note> - </trans-unit> <trans-unit id="Turn on" xml:space="preserve"> <source>Turn on</source> <target>Ввімкнути</target> @@ -5107,10 +5277,18 @@ You will be prompted to complete authentication before this feature is enabled.< <source>Unblock</source> <note>No comment provided by engineer.</note> </trans-unit> + <trans-unit id="Unblock for all" xml:space="preserve"> + <source>Unblock for all</source> + <note>No comment provided by engineer.</note> + </trans-unit> <trans-unit id="Unblock member" xml:space="preserve"> <source>Unblock member</source> <note>No comment provided by engineer.</note> </trans-unit> + <trans-unit id="Unblock member for all?" xml:space="preserve"> + <source>Unblock member for all?</source> + <note>No comment provided by engineer.</note> + </trans-unit> <trans-unit id="Unblock member?" xml:space="preserve"> <source>Unblock member?</source> <note>No comment provided by engineer.</note> @@ -5205,6 +5383,10 @@ To connect, please ask your contact to create another connection link and check <target>Непрочитане</target> <note>No comment provided by engineer.</note> </trans-unit> + <trans-unit id="Up to 100 last messages are sent to new members." xml:space="preserve"> + <source>Up to 100 last messages are sent to new members.</source> + <note>No comment provided by engineer.</note> + </trans-unit> <trans-unit id="Update" xml:space="preserve"> <source>Update</source> <target>Оновлення</target> @@ -5289,6 +5471,10 @@ To connect, please ask your contact to create another connection link and check <target>Використовуйте новий профіль інкогніто</target> <note>No comment provided by engineer.</note> </trans-unit> + <trans-unit id="Use only local notifications?" xml:space="preserve"> + <source>Use only local notifications?</source> + <note>No comment provided by engineer.</note> + </trans-unit> <trans-unit id="Use server" xml:space="preserve"> <source>Use server</source> <target>Використовувати сервер</target> @@ -5365,6 +5551,10 @@ To connect, please ask your contact to create another connection link and check <target>Переглянути код безпеки</target> <note>No comment provided by engineer.</note> </trans-unit> + <trans-unit id="Visible history" xml:space="preserve"> + <source>Visible history</source> + <note>chat feature</note> + </trans-unit> <trans-unit id="Voice messages" xml:space="preserve"> <source>Voice messages</source> <target>Голосові повідомлення</target> @@ -5449,11 +5639,19 @@ To connect, please ask your contact to create another connection link and check <target>Коли ви ділитеся з кимось своїм профілем інкогніто, цей профіль буде використовуватися для груп, до яких вас запрошують.</target> <note>No comment provided by engineer.</note> </trans-unit> + <trans-unit id="With encrypted files and media." xml:space="preserve"> + <source>With encrypted files and media.</source> + <note>No comment provided by engineer.</note> + </trans-unit> <trans-unit id="With optional welcome message." xml:space="preserve"> <source>With optional welcome message.</source> <target>З необов'язковим вітальним повідомленням.</target> <note>No comment provided by engineer.</note> </trans-unit> + <trans-unit id="With reduced battery usage." xml:space="preserve"> + <source>With reduced battery usage.</source> + <note>No comment provided by engineer.</note> + </trans-unit> <trans-unit id="Wrong database passphrase" xml:space="preserve"> <source>Wrong database passphrase</source> <target>Неправильний пароль до бази даних</target> @@ -5538,11 +5736,6 @@ Repeat join request?</source> <target>Ви можете приймати дзвінки з екрана блокування без автентифікації пристрою та програми.</target> <note>No comment provided by engineer.</note> </trans-unit> - <trans-unit id="You can also connect by clicking the link. If it opens in the browser, click **Open in mobile app** button." xml:space="preserve"> - <source>You can also connect by clicking the link. If it opens in the browser, click **Open in mobile app** button.</source> - <target>Ви також можете підключитися за посиланням. Якщо воно відкриється в браузері, натисніть кнопку **Відкрити в мобільному додатку**.</target> - <note>No comment provided by engineer.</note> - </trans-unit> <trans-unit id="You can create it later" xml:space="preserve"> <source>You can create it later</source> <target>Ви можете створити його пізніше</target> @@ -5563,6 +5756,10 @@ Repeat join request?</source> <target>Ви можете приховати або вимкнути звук профілю користувача - проведіть по ньому вправо.</target> <note>No comment provided by engineer.</note> </trans-unit> + <trans-unit id="You can make it visible to your SimpleX contacts via Settings." xml:space="preserve"> + <source>You can make it visible to your SimpleX contacts via Settings.</source> + <note>No comment provided by engineer.</note> + </trans-unit> <trans-unit id="You can now send messages to %@" xml:space="preserve"> <source>You can now send messages to %@</source> <target>Тепер ви можете надсилати повідомлення на адресу %@</target> @@ -5603,6 +5800,10 @@ Repeat join request?</source> <target>Ви можете використовувати розмітку для форматування повідомлень:</target> <note>No comment provided by engineer.</note> </trans-unit> + <trans-unit id="You can view invitation link again in connection details." xml:space="preserve"> + <source>You can view invitation link again in connection details.</source> + <note>No comment provided by engineer.</note> + </trans-unit> <trans-unit id="You can't send messages!" xml:space="preserve"> <source>You can't send messages!</source> <target>Ви не можете надсилати повідомлення!</target> @@ -5787,13 +5988,6 @@ You can cancel this connection and remove the contact (and try later with a new <target>Ваші контакти можуть дозволити повне видалення повідомлень.</target> <note>No comment provided by engineer.</note> </trans-unit> - <trans-unit id="Your contacts in SimpleX will see it. You can change it in Settings." xml:space="preserve"> - <source>Your contacts in SimpleX will see it. -You can change it in Settings.</source> - <target>Ваші контакти в SimpleX побачать це. -Ви можете змінити його в Налаштуваннях.</target> - <note>No comment provided by engineer.</note> - </trans-unit> <trans-unit id="Your contacts will remain connected." xml:space="preserve"> <source>Your contacts will remain connected.</source> <target>Ваші контакти залишаться на зв'язку.</target> @@ -5942,6 +6136,14 @@ SimpleX servers cannot see your profile.</source> <source>blocked</source> <note>No comment provided by engineer.</note> </trans-unit> + <trans-unit id="blocked %@" xml:space="preserve"> + <source>blocked %@</source> + <note>rcv group event chat item</note> + </trans-unit> + <trans-unit id="blocked by admin" xml:space="preserve"> + <source>blocked by admin</source> + <note>blocked chat item</note> + </trans-unit> <trans-unit id="bold" xml:space="preserve"> <source>bold</source> <target>жирний</target> @@ -6061,6 +6263,10 @@ SimpleX servers cannot see your profile.</source> <target>з'єднання:%@</target> <note>connection information</note> </trans-unit> + <trans-unit id="contact %@ changed to %@" xml:space="preserve"> + <source>contact %1$@ changed to %2$@</source> + <note>profile update event chat item</note> + </trans-unit> <trans-unit id="contact has e2e encryption" xml:space="preserve"> <source>contact has e2e encryption</source> <target>контакт має шифрування e2e</target> @@ -6330,6 +6536,10 @@ SimpleX servers cannot see your profile.</source> <target>учасник</target> <note>member role</note> </trans-unit> + <trans-unit id="member %@ changed to %@" xml:space="preserve"> + <source>member %1$@ changed to %2$@</source> + <note>profile update event chat item</note> + </trans-unit> <trans-unit id="member connected" xml:space="preserve"> <source>connected</source> <target>з'єднаний</target> @@ -6452,6 +6662,14 @@ SimpleX servers cannot see your profile.</source> <target>видалено %@</target> <note>rcv group event chat item</note> </trans-unit> + <trans-unit id="removed contact address" xml:space="preserve"> + <source>removed contact address</source> + <note>profile update event chat item</note> + </trans-unit> + <trans-unit id="removed profile picture" xml:space="preserve"> + <source>removed profile picture</source> + <note>profile update event chat item</note> + </trans-unit> <trans-unit id="removed you" xml:space="preserve"> <source>removed you</source> <target>прибрали вас</target> @@ -6481,6 +6699,14 @@ SimpleX servers cannot see your profile.</source> <source>send direct message</source> <note>No comment provided by engineer.</note> </trans-unit> + <trans-unit id="set new contact address" xml:space="preserve"> + <source>set new contact address</source> + <note>profile update event chat item</note> + </trans-unit> + <trans-unit id="set new profile picture" xml:space="preserve"> + <source>set new profile picture</source> + <note>profile update event chat item</note> + </trans-unit> <trans-unit id="starting…" xml:space="preserve"> <source>starting…</source> <target>починаючи…</target> @@ -6496,16 +6722,28 @@ SimpleX servers cannot see your profile.</source> <target>цей контакт</target> <note>notification title</note> </trans-unit> + <trans-unit id="unblocked %@" xml:space="preserve"> + <source>unblocked %@</source> + <note>rcv group event chat item</note> + </trans-unit> <trans-unit id="unknown" xml:space="preserve"> <source>unknown</source> <target>невідомий</target> <note>connection info</note> </trans-unit> + <trans-unit id="unknown status" xml:space="preserve"> + <source>unknown status</source> + <note>No comment provided by engineer.</note> + </trans-unit> <trans-unit id="updated group profile" xml:space="preserve"> <source>updated group profile</source> <target>оновлений профіль групи</target> <note>rcv group event chat item</note> </trans-unit> + <trans-unit id="updated profile" xml:space="preserve"> + <source>updated profile</source> + <note>profile update event chat item</note> + </trans-unit> <trans-unit id="v%@" xml:space="preserve"> <source>v%@</source> <note>No comment provided by engineer.</note> @@ -6575,6 +6813,10 @@ SimpleX servers cannot see your profile.</source> <target>ви спостерігач</target> <note>No comment provided by engineer.</note> </trans-unit> + <trans-unit id="you blocked %@" xml:space="preserve"> + <source>you blocked %@</source> + <note>snd group event chat item</note> + </trans-unit> <trans-unit id="you changed address" xml:space="preserve"> <source>you changed address</source> <target>ви змінили адресу</target> @@ -6615,6 +6857,10 @@ SimpleX servers cannot see your profile.</source> <target>ви поділилися одноразовим посиланням інкогніто</target> <note>chat list item description</note> </trans-unit> + <trans-unit id="you unblocked %@" xml:space="preserve"> + <source>you unblocked %@</source> + <note>snd group event chat item</note> + </trans-unit> <trans-unit id="you: " xml:space="preserve"> <source>you: </source> <target>ти: </target> diff --git a/apps/ios/SimpleX Localizations/zh-Hans.xcloc/Localized Contents/zh-Hans.xliff b/apps/ios/SimpleX Localizations/zh-Hans.xcloc/Localized Contents/zh-Hans.xliff index d96537be3e..6209cfb41f 100644 --- a/apps/ios/SimpleX Localizations/zh-Hans.xcloc/Localized Contents/zh-Hans.xliff +++ b/apps/ios/SimpleX Localizations/zh-Hans.xcloc/Localized Contents/zh-Hans.xliff @@ -212,6 +212,10 @@ <source>%lld messages blocked</source> <note>No comment provided by engineer.</note> </trans-unit> + <trans-unit id="%lld messages blocked by admin" xml:space="preserve"> + <source>%lld messages blocked by admin</source> + <note>No comment provided by engineer.</note> + </trans-unit> <trans-unit id="%lld messages marked deleted" xml:space="preserve"> <source>%lld messages marked deleted</source> <note>No comment provided by engineer.</note> @@ -303,14 +307,17 @@ <target>)</target> <note>No comment provided by engineer.</note> </trans-unit> + <trans-unit id="**Add contact**: to create a new invitation link, or connect via a link you received." xml:space="preserve"> + <source>**Add contact**: to create a new invitation link, or connect via a link you received.</source> + <note>No comment provided by engineer.</note> + </trans-unit> <trans-unit id="**Add new contact**: to create your one-time QR Code for your contact." xml:space="preserve"> <source>**Add new contact**: to create your one-time QR Code or link for your contact.</source> <target>**添加新联系人**:为您的联系人创建一次性二维码或者链接。</target> <note>No comment provided by engineer.</note> </trans-unit> - <trans-unit id="**Create link / QR code** for your contact to use." xml:space="preserve"> - <source>**Create link / QR code** for your contact to use.</source> - <target>**创建链接 / 二维码** 给您的联系人使用。</target> + <trans-unit id="**Create group**: to create a new group." xml:space="preserve"> + <source>**Create group**: to create a new group.</source> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="**More private**: check new messages every 20 minutes. Device token is shared with SimpleX Chat server, but not how many contacts or messages you have." xml:space="preserve"> @@ -323,11 +330,6 @@ <target>**最私密**:不使用 SimpleX Chat 通知服务器,在后台定期检查消息(取决于您多经常使用应用程序)。</target> <note>No comment provided by engineer.</note> </trans-unit> - <trans-unit id="**Paste received link** or open it in the browser and tap **Open in mobile app**." xml:space="preserve"> - <source>**Paste received link** or open it in the browser and tap **Open in mobile app**.</source> - <target>**粘贴收到的链接**或者在浏览器里打开并且点击**在移动应用程序里打开**。</target> - <note>No comment provided by engineer.</note> - </trans-unit> <trans-unit id="**Please note**: you will NOT be able to recover or change passphrase if you lose it." xml:space="preserve"> <source>**Please note**: you will NOT be able to recover or change passphrase if you lose it.</source> <target>**请注意**:如果您丢失密码,您将无法恢复或者更改密码。</target> @@ -338,11 +340,6 @@ <target>**推荐**:设备令牌和通知会发送至 SimpleX Chat 通知服务器,但是消息内容、大小或者发送人不会。</target> <note>No comment provided by engineer.</note> </trans-unit> - <trans-unit id="**Scan QR code**: to connect to your contact in person or via video call." xml:space="preserve"> - <source>**Scan QR code**: to connect to your contact in person or via video call.</source> - <target>**扫描二维码**:见面或者通过视频通话来连接您的联系人。</target> - <note>No comment provided by engineer.</note> - </trans-unit> <trans-unit id="**Warning**: Instant push notifications require passphrase saved in Keychain." xml:space="preserve"> <source>**Warning**: Instant push notifications require passphrase saved in Keychain.</source> <target>**警告**:及时推送通知需要保存在钥匙串的密码。</target> @@ -440,11 +437,6 @@ <target>1周</target> <note>time interval</note> </trans-unit> - <trans-unit id="1-time link" xml:space="preserve"> - <source>1-time link</source> - <target>一次性链接</target> - <note>No comment provided by engineer.</note> - </trans-unit> <trans-unit id="5 minutes" xml:space="preserve"> <source>5 minutes</source> <target>5分钟</target> @@ -560,6 +552,10 @@ <target>将地址添加到您的个人资料,以便您的联系人可以与其他人共享。个人资料更新将发送给您的联系人。</target> <note>No comment provided by engineer.</note> </trans-unit> + <trans-unit id="Add contact" xml:space="preserve"> + <source>Add contact</source> + <note>No comment provided by engineer.</note> + </trans-unit> <trans-unit id="Add preset servers" xml:space="preserve"> <source>Add preset servers</source> <target>添加预设服务器</target> @@ -630,6 +626,10 @@ <target>所有群组成员将保持连接。</target> <note>No comment provided by engineer.</note> </trans-unit> + <trans-unit id="All messages will be deleted - this cannot be undone!" xml:space="preserve"> + <source>All messages will be deleted - this cannot be undone!</source> + <note>No comment provided by engineer.</note> + </trans-unit> <trans-unit id="All messages will be deleted - this cannot be undone! The messages will be deleted ONLY for you." xml:space="preserve"> <source>All messages will be deleted - this cannot be undone! The messages will be deleted ONLY for you.</source> <target>所有聊天记录和消息将被删除——这一行为无法撤销!只有您的消息会被删除。</target> @@ -664,8 +664,8 @@ <target>仅当您的联系人允许时才允许限时消息。</target> <note>No comment provided by engineer.</note> </trans-unit> - <trans-unit id="Allow irreversible message deletion only if your contact allows it to you." xml:space="preserve"> - <source>Allow irreversible message deletion only if your contact allows it to you.</source> + <trans-unit id="Allow irreversible message deletion only if your contact allows it to you. (24 hours)" xml:space="preserve"> + <source>Allow irreversible message deletion only if your contact allows it to you. (24 hours)</source> <target>仅有您的联系人许可后才允许不可撤回消息移除。</target> <note>No comment provided by engineer.</note> </trans-unit> @@ -689,8 +689,8 @@ <target>允许发送限时消息。</target> <note>No comment provided by engineer.</note> </trans-unit> - <trans-unit id="Allow to irreversibly delete sent messages." xml:space="preserve"> - <source>Allow to irreversibly delete sent messages.</source> + <trans-unit id="Allow to irreversibly delete sent messages. (24 hours)" xml:space="preserve"> + <source>Allow to irreversibly delete sent messages. (24 hours)</source> <target>允许不可撤回地删除已发送消息。</target> <note>No comment provided by engineer.</note> </trans-unit> @@ -724,8 +724,8 @@ <target>允许您的联系人给您打电话。</target> <note>No comment provided by engineer.</note> </trans-unit> - <trans-unit id="Allow your contacts to irreversibly delete sent messages." xml:space="preserve"> - <source>Allow your contacts to irreversibly delete sent messages.</source> + <trans-unit id="Allow your contacts to irreversibly delete sent messages. (24 hours)" xml:space="preserve"> + <source>Allow your contacts to irreversibly delete sent messages. (24 hours)</source> <target>允许您的联系人不可撤回地删除已发送消息。</target> <note>No comment provided by engineer.</note> </trans-unit> @@ -899,6 +899,10 @@ <source>Block</source> <note>No comment provided by engineer.</note> </trans-unit> + <trans-unit id="Block for all" xml:space="preserve"> + <source>Block for all</source> + <note>No comment provided by engineer.</note> + </trans-unit> <trans-unit id="Block group members" xml:space="preserve"> <source>Block group members</source> <note>No comment provided by engineer.</note> @@ -907,17 +911,25 @@ <source>Block member</source> <note>No comment provided by engineer.</note> </trans-unit> + <trans-unit id="Block member for all?" xml:space="preserve"> + <source>Block member for all?</source> + <note>No comment provided by engineer.</note> + </trans-unit> <trans-unit id="Block member?" xml:space="preserve"> <source>Block member?</source> <note>No comment provided by engineer.</note> </trans-unit> + <trans-unit id="Blocked by admin" xml:space="preserve"> + <source>Blocked by admin</source> + <note>No comment provided by engineer.</note> + </trans-unit> <trans-unit id="Both you and your contact can add message reactions." xml:space="preserve"> <source>Both you and your contact can add message reactions.</source> <target>您和您的联系人都可以添加消息回应。</target> <note>No comment provided by engineer.</note> </trans-unit> - <trans-unit id="Both you and your contact can irreversibly delete sent messages." xml:space="preserve"> - <source>Both you and your contact can irreversibly delete sent messages.</source> + <trans-unit id="Both you and your contact can irreversibly delete sent messages. (24 hours)" xml:space="preserve"> + <source>Both you and your contact can irreversibly delete sent messages. (24 hours)</source> <target>您和您的联系人都可以不可逆转地删除已发送的消息。</target> <note>No comment provided by engineer.</note> </trans-unit> @@ -956,9 +968,8 @@ <target>通话</target> <note>No comment provided by engineer.</note> </trans-unit> - <trans-unit id="Can't delete user profile!" xml:space="preserve"> - <source>Can't delete user profile!</source> - <target>无法删除用户个人资料!</target> + <trans-unit id="Camera not available" xml:space="preserve"> + <source>Camera not available</source> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="Can't invite contact!" xml:space="preserve"> @@ -1072,6 +1083,10 @@ <target>聊天已停止</target> <note>No comment provided by engineer.</note> </trans-unit> + <trans-unit id="Chat is stopped. If you already used this database on another device, you should transfer it back before starting chat." xml:space="preserve"> + <source>Chat is stopped. If you already used this database on another device, you should transfer it back before starting chat.</source> + <note>No comment provided by engineer.</note> + </trans-unit> <trans-unit id="Chat preferences" xml:space="preserve"> <source>Chat preferences</source> <target>聊天偏好设置</target> @@ -1117,6 +1132,10 @@ <target>清除对话吗?</target> <note>No comment provided by engineer.</note> </trans-unit> + <trans-unit id="Clear private notes?" xml:space="preserve"> + <source>Clear private notes?</source> + <note>No comment provided by engineer.</note> + </trans-unit> <trans-unit id="Clear verification" xml:space="preserve"> <source>Clear verification</source> <target>清除验证</target> @@ -1208,11 +1227,6 @@ This is your own one-time link!</source> <target>通过链接连接</target> <note>No comment provided by engineer.</note> </trans-unit> - <trans-unit id="Connect via link / QR code" xml:space="preserve"> - <source>Connect via link / QR code</source> - <target>通过群组链接/二维码连接</target> - <note>No comment provided by engineer.</note> - </trans-unit> <trans-unit id="Connect via one-time link" xml:space="preserve"> <source>Connect via one-time link</source> <target>通过一次性链接连接</target> @@ -1380,11 +1394,6 @@ This is your own one-time link!</source> <target>在[桌面应用程序](https://simplex.chat/downloads/)中创建新的个人资料。 💻</target> <note>No comment provided by engineer.</note> </trans-unit> - <trans-unit id="Create one-time invitation link" xml:space="preserve"> - <source>Create one-time invitation link</source> - <target>创建一次性邀请链接</target> - <note>No comment provided by engineer.</note> - </trans-unit> <trans-unit id="Create profile" xml:space="preserve"> <source>Create profile</source> <note>No comment provided by engineer.</note> @@ -1404,11 +1413,23 @@ This is your own one-time link!</source> <target>创建您的资料</target> <note>No comment provided by engineer.</note> </trans-unit> + <trans-unit id="Created at" xml:space="preserve"> + <source>Created at</source> + <note>No comment provided by engineer.</note> + </trans-unit> + <trans-unit id="Created at: %@" xml:space="preserve"> + <source>Created at: %@</source> + <note>copied message info</note> + </trans-unit> <trans-unit id="Created on %@" xml:space="preserve"> <source>Created on %@</source> <target>创建于 %@</target> <note>No comment provided by engineer.</note> </trans-unit> + <trans-unit id="Creating link…" xml:space="preserve"> + <source>Creating link…</source> + <note>No comment provided by engineer.</note> + </trans-unit> <trans-unit id="Current Passcode" xml:space="preserve"> <source>Current Passcode</source> <target>当前密码</target> @@ -1880,6 +1901,10 @@ This cannot be undone!</source> <target>稍后再做</target> <note>No comment provided by engineer.</note> </trans-unit> + <trans-unit id="Do not send history to new members." xml:space="preserve"> + <source>Do not send history to new members.</source> + <note>No comment provided by engineer.</note> + </trans-unit> <trans-unit id="Don't create address" xml:space="preserve"> <source>Don't create address</source> <target>不创建地址</target> @@ -1950,6 +1975,10 @@ This cannot be undone!</source> <target>启用自动删除消息?</target> <note>No comment provided by engineer.</note> </trans-unit> + <trans-unit id="Enable camera access" xml:space="preserve"> + <source>Enable camera access</source> + <note>No comment provided by engineer.</note> + </trans-unit> <trans-unit id="Enable for all" xml:space="preserve"> <source>Enable for all</source> <target>全部启用</target> @@ -2015,6 +2044,10 @@ This cannot be undone!</source> <target>加密消息或其他事件</target> <note>notification</note> </trans-unit> + <trans-unit id="Encrypted message: app is stopped" xml:space="preserve"> + <source>Encrypted message: app is stopped</source> + <note>notification</note> + </trans-unit> <trans-unit id="Encrypted message: database error" xml:space="preserve"> <source>Encrypted message: database error</source> <target>加密消息:数据库错误</target> @@ -2155,6 +2188,10 @@ This cannot be undone!</source> <target>创建成员联系人时出错</target> <note>No comment provided by engineer.</note> </trans-unit> + <trans-unit id="Error creating message" xml:space="preserve"> + <source>Error creating message</source> + <note>No comment provided by engineer.</note> + </trans-unit> <trans-unit id="Error creating profile!" xml:space="preserve"> <source>Error creating profile!</source> <target>创建资料错误!</target> @@ -2240,6 +2277,10 @@ This cannot be undone!</source> <target>加载 %@ 服务器错误</target> <note>No comment provided by engineer.</note> </trans-unit> + <trans-unit id="Error opening chat" xml:space="preserve"> + <source>Error opening chat</source> + <note>No comment provided by engineer.</note> + </trans-unit> <trans-unit id="Error receiving file" xml:space="preserve"> <source>Error receiving file</source> <target>接收文件错误</target> @@ -2280,6 +2321,10 @@ This cannot be undone!</source> <target>保存用户密码时出错</target> <note>No comment provided by engineer.</note> </trans-unit> + <trans-unit id="Error scanning code: %@" xml:space="preserve"> + <source>Error scanning code: %@</source> + <note>No comment provided by engineer.</note> + </trans-unit> <trans-unit id="Error sending email" xml:space="preserve"> <source>Error sending email</source> <target>发送电邮错误</target> @@ -2604,8 +2649,8 @@ This cannot be undone!</source> <target>群组成员可以添加信息回应。</target> <note>No comment provided by engineer.</note> </trans-unit> - <trans-unit id="Group members can irreversibly delete sent messages." xml:space="preserve"> - <source>Group members can irreversibly delete sent messages.</source> + <trans-unit id="Group members can irreversibly delete sent messages. (24 hours)" xml:space="preserve"> + <source>Group members can irreversibly delete sent messages. (24 hours)</source> <target>群组成员可以不可撤回地删除已发送的消息。</target> <note>No comment provided by engineer.</note> </trans-unit> @@ -2714,6 +2759,10 @@ This cannot be undone!</source> <target>历史记录</target> <note>No comment provided by engineer.</note> </trans-unit> + <trans-unit id="History is not sent to new members." xml:space="preserve"> + <source>History is not sent to new members.</source> + <note>No comment provided by engineer.</note> + </trans-unit> <trans-unit id="How SimpleX works" xml:space="preserve"> <source>How SimpleX works</source> <target>SimpleX的工作原理</target> @@ -2749,11 +2798,6 @@ This cannot be undone!</source> <target>如果您不能亲自见面,可以在视频通话中展示二维码,或分享链接。</target> <note>No comment provided by engineer.</note> </trans-unit> - <trans-unit id="If you cannot meet in person, you can **scan QR code in the video call**, or your contact can share an invitation link." xml:space="preserve"> - <source>If you cannot meet in person, you can **scan QR code in the video call**, or your contact can share an invitation link.</source> - <target>如果您不能亲自见面,您可以**扫描视频通话中的二维码**,或者您的联系人可以分享邀请链接。</target> - <note>No comment provided by engineer.</note> - </trans-unit> <trans-unit id="If you enter this passcode when opening the app, all app data will be irreversibly removed!" xml:space="preserve"> <source>If you enter this passcode when opening the app, all app data will be irreversibly removed!</source> <target>如果您在打开应用时输入该密码,所有应用程序数据将被不可撤回地删除!</target> @@ -2809,6 +2853,10 @@ This cannot be undone!</source> <target>导入数据库</target> <note>No comment provided by engineer.</note> </trans-unit> + <trans-unit id="Improved message delivery" xml:space="preserve"> + <source>Improved message delivery</source> + <note>No comment provided by engineer.</note> + </trans-unit> <trans-unit id="Improved privacy and security" xml:space="preserve"> <source>Improved privacy and security</source> <target>改进的隐私和安全</target> @@ -2909,15 +2957,31 @@ This cannot be undone!</source> <target>界面</target> <note>No comment provided by engineer.</note> </trans-unit> + <trans-unit id="Invalid QR code" xml:space="preserve"> + <source>Invalid QR code</source> + <note>No comment provided by engineer.</note> + </trans-unit> <trans-unit id="Invalid connection link" xml:space="preserve"> <source>Invalid connection link</source> <target>无效的连接链接</target> <note>No comment provided by engineer.</note> </trans-unit> + <trans-unit id="Invalid display name!" xml:space="preserve"> + <source>Invalid display name!</source> + <note>No comment provided by engineer.</note> + </trans-unit> + <trans-unit id="Invalid link" xml:space="preserve"> + <source>Invalid link</source> + <note>No comment provided by engineer.</note> + </trans-unit> <trans-unit id="Invalid name!" xml:space="preserve"> <source>Invalid name!</source> <note>No comment provided by engineer.</note> </trans-unit> + <trans-unit id="Invalid response" xml:space="preserve"> + <source>Invalid response</source> + <note>No comment provided by engineer.</note> + </trans-unit> <trans-unit id="Invalid server address!" xml:space="preserve"> <source>Invalid server address!</source> <target>无效的服务器地址!</target> @@ -3009,6 +3073,10 @@ This cannot be undone!</source> <target>加入群组</target> <note>No comment provided by engineer.</note> </trans-unit> + <trans-unit id="Join group conversations" xml:space="preserve"> + <source>Join group conversations</source> + <note>No comment provided by engineer.</note> + </trans-unit> <trans-unit id="Join group?" xml:space="preserve"> <source>Join group?</source> <note>No comment provided by engineer.</note> @@ -3032,10 +3100,18 @@ This is your link for group %@!</source> <target>加入群组中</target> <note>No comment provided by engineer.</note> </trans-unit> + <trans-unit id="Keep" xml:space="preserve"> + <source>Keep</source> + <note>No comment provided by engineer.</note> + </trans-unit> <trans-unit id="Keep the app open to use it from desktop" xml:space="preserve"> <source>Keep the app open to use it from desktop</source> <note>No comment provided by engineer.</note> </trans-unit> + <trans-unit id="Keep unused invitation?" xml:space="preserve"> + <source>Keep unused invitation?</source> + <note>No comment provided by engineer.</note> + </trans-unit> <trans-unit id="Keep your connections" xml:space="preserve"> <source>Keep your connections</source> <target>保持连接</target> @@ -3118,6 +3194,11 @@ This is your link for group %@!</source> <target>实时消息</target> <note>No comment provided by engineer.</note> </trans-unit> + <trans-unit id="Local" xml:space="preserve"> + <source>Local</source> + <target>本地</target> + <note>No comment provided by engineer.</note> + </trans-unit> <trans-unit id="Local name" xml:space="preserve"> <source>Local name</source> <target>本地名称</target> @@ -3357,6 +3438,10 @@ This is your link for group %@!</source> <target>新密码</target> <note>No comment provided by engineer.</note> </trans-unit> + <trans-unit id="New chat" xml:space="preserve"> + <source>New chat</source> + <note>No comment provided by engineer.</note> + </trans-unit> <trans-unit id="New contact request" xml:space="preserve"> <source>New contact request</source> <target>新联系人请求</target> @@ -3480,16 +3565,15 @@ This is your link for group %@!</source> - 禁用成员(“观察员”角色)</target> <note>No comment provided by engineer.</note> </trans-unit> + <trans-unit id="OK" xml:space="preserve"> + <source>OK</source> + <note>No comment provided by engineer.</note> + </trans-unit> <trans-unit id="Off" xml:space="preserve"> <source>Off</source> <target>关闭</target> <note>No comment provided by engineer.</note> </trans-unit> - <trans-unit id="Off (Local)" xml:space="preserve"> - <source>Off (Local)</source> - <target>关闭(本地)</target> - <note>No comment provided by engineer.</note> - </trans-unit> <trans-unit id="Ok" xml:space="preserve"> <source>Ok</source> <target>好的</target> @@ -3550,8 +3634,8 @@ This is your link for group %@!</source> <target>只有您可以添加消息回应。</target> <note>No comment provided by engineer.</note> </trans-unit> - <trans-unit id="Only you can irreversibly delete messages (your contact can mark them for deletion)." xml:space="preserve"> - <source>Only you can irreversibly delete messages (your contact can mark them for deletion).</source> + <trans-unit id="Only you can irreversibly delete messages (your contact can mark them for deletion). (24 hours)" xml:space="preserve"> + <source>Only you can irreversibly delete messages (your contact can mark them for deletion). (24 hours)</source> <target>只有您可以不可撤回地删除消息(您的联系人可以将它们标记为删除)。</target> <note>No comment provided by engineer.</note> </trans-unit> @@ -3575,8 +3659,8 @@ This is your link for group %@!</source> <target>只有您的联系人可以添加消息回应。</target> <note>No comment provided by engineer.</note> </trans-unit> - <trans-unit id="Only your contact can irreversibly delete messages (you can mark them for deletion)." xml:space="preserve"> - <source>Only your contact can irreversibly delete messages (you can mark them for deletion).</source> + <trans-unit id="Only your contact can irreversibly delete messages (you can mark them for deletion). (24 hours)" xml:space="preserve"> + <source>Only your contact can irreversibly delete messages (you can mark them for deletion). (24 hours)</source> <target>只有您的联系人才能不可撤回地删除消息(您可以将它们标记为删除)。</target> <note>No comment provided by engineer.</note> </trans-unit> @@ -3629,9 +3713,16 @@ This is your link for group %@!</source> <target>开源协议和代码——任何人都可以运行服务器。</target> <note>No comment provided by engineer.</note> </trans-unit> - <trans-unit id="Opening database…" xml:space="preserve"> - <source>Opening database…</source> - <target>打开数据库中……</target> + <trans-unit id="Opening app…" xml:space="preserve"> + <source>Opening app…</source> + <note>No comment provided by engineer.</note> + </trans-unit> + <trans-unit id="Or scan QR code" xml:space="preserve"> + <source>Or scan QR code</source> + <note>No comment provided by engineer.</note> + </trans-unit> + <trans-unit id="Or show this code" xml:space="preserve"> + <source>Or show this code</source> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="PING count" xml:space="preserve"> @@ -3674,10 +3765,9 @@ This is your link for group %@!</source> <target>显示密码</target> <note>No comment provided by engineer.</note> </trans-unit> - <trans-unit id="Paste" xml:space="preserve"> - <source>Paste</source> - <target>粘贴</target> - <note>No comment provided by engineer.</note> + <trans-unit id="Past member %@" xml:space="preserve"> + <source>Past member %@</source> + <note>past/unknown group member</note> </trans-unit> <trans-unit id="Paste desktop address" xml:space="preserve"> <source>Paste desktop address</source> @@ -3688,15 +3778,13 @@ This is your link for group %@!</source> <target>粘贴图片</target> <note>No comment provided by engineer.</note> </trans-unit> - <trans-unit id="Paste received link" xml:space="preserve"> - <source>Paste received link</source> - <target>粘贴收到的链接</target> + <trans-unit id="Paste link to connect!" xml:space="preserve"> + <source>Paste link to connect!</source> <note>No comment provided by engineer.</note> </trans-unit> - <trans-unit id="Paste the link you received to connect with your contact." xml:space="preserve"> - <source>Paste the link you received to connect with your contact.</source> - <target>将您收到的链接粘贴到下面的框中以与您的联系人联系。</target> - <note>placeholder</note> + <trans-unit id="Paste the link you received" xml:space="preserve"> + <source>Paste the link you received</source> + <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="People can connect to you only via the links you share." xml:space="preserve"> <source>People can connect to you only via the links you share.</source> @@ -3733,6 +3821,11 @@ This is your link for group %@!</source> <target>请检查您和您的联系人偏好设置。</target> <note>No comment provided by engineer.</note> </trans-unit> + <trans-unit id="Please contact developers. Error: %@" xml:space="preserve"> + <source>Please contact developers. +Error: %@</source> + <note>No comment provided by engineer.</note> + </trans-unit> <trans-unit id="Please contact group admin." xml:space="preserve"> <source>Please contact group admin.</source> <target>请联系群组管理员。</target> @@ -3818,6 +3911,10 @@ This is your link for group %@!</source> <target>私密文件名</target> <note>No comment provided by engineer.</note> </trans-unit> + <trans-unit id="Private notes" xml:space="preserve"> + <source>Private notes</source> + <note>name of notes to self</note> + </trans-unit> <trans-unit id="Profile and server connections" xml:space="preserve"> <source>Profile and server connections</source> <target>资料和服务器连接</target> @@ -3936,6 +4033,10 @@ This is your link for group %@!</source> <target>在 [用户指南](https://simplex.chat/docs/guide/app-settings.html#your-simplex-contact-address) 中阅读更多内容。</target> <note>No comment provided by engineer.</note> </trans-unit> + <trans-unit id="Read more in [User Guide](https://simplex.chat/docs/guide/chat-profiles.html#incognito-mode)." xml:space="preserve"> + <source>Read more in [User Guide](https://simplex.chat/docs/guide/chat-profiles.html#incognito-mode).</source> + <note>No comment provided by engineer.</note> + </trans-unit> <trans-unit id="Read more in [User Guide](https://simplex.chat/docs/guide/readme.html#connect-to-friends)." xml:space="preserve"> <source>Read more in [User Guide](https://simplex.chat/docs/guide/readme.html#connect-to-friends).</source> <target>在 [用户指南](https://simplex.chat/docs/guide/readme.html#connect-to-friends) 中阅读更多内容。</target> @@ -3991,6 +4092,10 @@ This is your link for group %@!</source> <target>接收通过</target> <note>No comment provided by engineer.</note> </trans-unit> + <trans-unit id="Recent history and improved [directory bot](simplex:/contact#/?v=1-4&smp=smp%3A%2F%2Fu2dS9sG8nMNURyZwqASV4yROM28Er0luVTx5X1CsMrU%3D%40smp4.simplex.im%2FeXSPwqTkKyDO3px4fLf1wx3MvPdjdLW3%23%2F%3Fv%3D1-2%26dh%3DMCowBQYDK2VuAyEAaiv6MkMH44L2TcYrt_CsX3ZvM11WgbMEUn0hkIKTOho%253D%26srv%3Do5vmywmrnaxalvz6wi3zicyftgio6psuvyniis6gco6bp6ekl4cqj4id.onion)." xml:space="preserve"> + <source>Recent history and improved [directory bot](simplex:/contact#/?v=1-4&smp=smp%3A%2F%2Fu2dS9sG8nMNURyZwqASV4yROM28Er0luVTx5X1CsMrU%3D%40smp4.simplex.im%2FeXSPwqTkKyDO3px4fLf1wx3MvPdjdLW3%23%2F%3Fv%3D1-2%26dh%3DMCowBQYDK2VuAyEAaiv6MkMH44L2TcYrt_CsX3ZvM11WgbMEUn0hkIKTOho%253D%26srv%3Do5vmywmrnaxalvz6wi3zicyftgio6psuvyniis6gco6bp6ekl4cqj4id.onion).</source> + <note>No comment provided by engineer.</note> + </trans-unit> <trans-unit id="Recipients see updates as you type them." xml:space="preserve"> <source>Recipients see updates as you type them.</source> <target>对方会在您键入时看到更新。</target> @@ -4144,6 +4249,10 @@ This is your link for group %@!</source> <target>恢复数据库错误</target> <note>No comment provided by engineer.</note> </trans-unit> + <trans-unit id="Retry" xml:space="preserve"> + <source>Retry</source> + <note>No comment provided by engineer.</note> + </trans-unit> <trans-unit id="Reveal" xml:space="preserve"> <source>Reveal</source> <target>揭示</target> @@ -4269,6 +4378,10 @@ This is your link for group %@!</source> <target>已保存的WebRTC ICE服务器将被删除</target> <note>No comment provided by engineer.</note> </trans-unit> + <trans-unit id="Saved message" xml:space="preserve"> + <source>Saved message</source> + <note>message info title</note> + </trans-unit> <trans-unit id="Scan QR code" xml:space="preserve"> <source>Scan QR code</source> <target>扫描二维码</target> @@ -4298,6 +4411,14 @@ This is your link for group %@!</source> <target>搜索</target> <note>No comment provided by engineer.</note> </trans-unit> + <trans-unit id="Search bar accepts invitation links." xml:space="preserve"> + <source>Search bar accepts invitation links.</source> + <note>No comment provided by engineer.</note> + </trans-unit> + <trans-unit id="Search or paste SimpleX link" xml:space="preserve"> + <source>Search or paste SimpleX link</source> + <note>No comment provided by engineer.</note> + </trans-unit> <trans-unit id="Secure queue" xml:space="preserve"> <source>Secure queue</source> <target>保护队列</target> @@ -4403,6 +4524,10 @@ This is your link for group %@!</source> <target>发送它们来自图库或自定义键盘。</target> <note>No comment provided by engineer.</note> </trans-unit> + <trans-unit id="Send up to 100 last messages to new members." xml:space="preserve"> + <source>Send up to 100 last messages to new members.</source> + <note>No comment provided by engineer.</note> + </trans-unit> <trans-unit id="Sender cancelled file transfer." xml:space="preserve"> <source>Sender cancelled file transfer.</source> <target>发送人已取消文件传输。</target> @@ -4572,9 +4697,8 @@ This is your link for group %@!</source> <target>分享链接</target> <note>No comment provided by engineer.</note> </trans-unit> - <trans-unit id="Share one-time invitation link" xml:space="preserve"> - <source>Share one-time invitation link</source> - <target>分享一次性邀请链接</target> + <trans-unit id="Share this 1-time invite link" xml:space="preserve"> + <source>Share this 1-time invite link</source> <note>No comment provided by engineer.</note> </trans-unit> <trans-unit id="Share with contacts" xml:space="preserve"> @@ -4697,16 +4821,15 @@ This is your link for group %@!</source> <target>某人</target> <note>notification title</note> </trans-unit> - <trans-unit id="Start a new chat" xml:space="preserve"> - <source>Start a new chat</source> - <target>开始新聊天</target> - <note>No comment provided by engineer.</note> - </trans-unit> <trans-unit id="Start chat" xml:space="preserve"> <source>Start chat</source> <target>开始聊天</target> <note>No comment provided by engineer.</note> </trans-unit> + <trans-unit id="Start chat?" xml:space="preserve"> + <source>Start chat?</source> + <note>No comment provided by engineer.</note> + </trans-unit> <trans-unit id="Start migration" xml:space="preserve"> <source>Start migration</source> <target>开始迁移</target> @@ -4831,6 +4954,14 @@ This is your link for group %@!</source> <target>点击以加入隐身聊天</target> <note>No comment provided by engineer.</note> </trans-unit> + <trans-unit id="Tap to paste link" xml:space="preserve"> + <source>Tap to paste link</source> + <note>No comment provided by engineer.</note> + </trans-unit> + <trans-unit id="Tap to scan" xml:space="preserve"> + <source>Tap to scan</source> + <note>No comment provided by engineer.</note> + </trans-unit> <trans-unit id="Tap to start a new chat" xml:space="preserve"> <source>Tap to start a new chat</source> <target>点击开始一个新聊天</target> @@ -4893,6 +5024,10 @@ It can happen because of some bug or when the connection is compromised.</source <target>更改数据库密码的尝试未完成。</target> <note>No comment provided by engineer.</note> </trans-unit> + <trans-unit id="The code you scanned is not a SimpleX link QR code." xml:space="preserve"> + <source>The code you scanned is not a SimpleX link QR code.</source> + <note>No comment provided by engineer.</note> + </trans-unit> <trans-unit id="The connection you accepted will be cancelled!" xml:space="preserve"> <source>The connection you accepted will be cancelled!</source> <target>您接受的连接将被取消!</target> @@ -4958,21 +5093,15 @@ It can happen because of some bug or when the connection is compromised.</source <target>您当前聊天资料 **%@** 的新连接服务器。</target> <note>No comment provided by engineer.</note> </trans-unit> + <trans-unit id="The text you pasted is not a SimpleX link." xml:space="preserve"> + <source>The text you pasted is not a SimpleX link.</source> + <note>No comment provided by engineer.</note> + </trans-unit> <trans-unit id="Theme" xml:space="preserve"> <source>Theme</source> <target>主题</target> <note>No comment provided by engineer.</note> </trans-unit> - <trans-unit id="There should be at least one user profile." xml:space="preserve"> - <source>There should be at least one user profile.</source> - <target>应该至少有一个用户资料。</target> - <note>No comment provided by engineer.</note> - </trans-unit> - <trans-unit id="There should be at least one visible user profile." xml:space="preserve"> - <source>There should be at least one visible user profile.</source> - <target>应该至少有一个可见的用户资料。</target> - <note>No comment provided by engineer.</note> - </trans-unit> <trans-unit id="These settings are for your current profile **%@**." xml:space="preserve"> <source>These settings are for your current profile **%@**.</source> <target>这些设置适用于您当前的配置文件 **%@**。</target> @@ -5002,6 +5131,10 @@ It can happen because of some bug or when the connection is compromised.</source <source>This device name</source> <note>No comment provided by engineer.</note> </trans-unit> + <trans-unit id="This display name is invalid. Please choose another name." xml:space="preserve"> + <source>This display name is invalid. Please choose another name.</source> + <note>No comment provided by engineer.</note> + </trans-unit> <trans-unit id="This group has over %lld members, delivery receipts are not sent." xml:space="preserve"> <source>This group has over %lld members, delivery receipts are not sent.</source> <target>该组有超过 %lld 个成员,不发送送货单。</target> @@ -5101,16 +5234,15 @@ You will be prompted to complete authentication before this feature is enabled.< <target>正在尝试连接到用于从该联系人接收消息的服务器。</target> <note>No comment provided by engineer.</note> </trans-unit> + <trans-unit id="Turkish interface" xml:space="preserve"> + <source>Turkish interface</source> + <note>No comment provided by engineer.</note> + </trans-unit> <trans-unit id="Turn off" xml:space="preserve"> <source>Turn off</source> <target>关闭</target> <note>No comment provided by engineer.</note> </trans-unit> - <trans-unit id="Turn off notifications?" xml:space="preserve"> - <source>Turn off notifications?</source> - <target>关闭通知?</target> - <note>No comment provided by engineer.</note> - </trans-unit> <trans-unit id="Turn on" xml:space="preserve"> <source>Turn on</source> <target>打开</target> @@ -5125,10 +5257,18 @@ You will be prompted to complete authentication before this feature is enabled.< <source>Unblock</source> <note>No comment provided by engineer.</note> </trans-unit> + <trans-unit id="Unblock for all" xml:space="preserve"> + <source>Unblock for all</source> + <note>No comment provided by engineer.</note> + </trans-unit> <trans-unit id="Unblock member" xml:space="preserve"> <source>Unblock member</source> <note>No comment provided by engineer.</note> </trans-unit> + <trans-unit id="Unblock member for all?" xml:space="preserve"> + <source>Unblock member for all?</source> + <note>No comment provided by engineer.</note> + </trans-unit> <trans-unit id="Unblock member?" xml:space="preserve"> <source>Unblock member?</source> <note>No comment provided by engineer.</note> @@ -5223,6 +5363,10 @@ To connect, please ask your contact to create another connection link and check <target>未读</target> <note>No comment provided by engineer.</note> </trans-unit> + <trans-unit id="Up to 100 last messages are sent to new members." xml:space="preserve"> + <source>Up to 100 last messages are sent to new members.</source> + <note>No comment provided by engineer.</note> + </trans-unit> <trans-unit id="Update" xml:space="preserve"> <source>Update</source> <target>更新</target> @@ -5307,6 +5451,10 @@ To connect, please ask your contact to create another connection link and check <target>使用新的隐身配置文件</target> <note>No comment provided by engineer.</note> </trans-unit> + <trans-unit id="Use only local notifications?" xml:space="preserve"> + <source>Use only local notifications?</source> + <note>No comment provided by engineer.</note> + </trans-unit> <trans-unit id="Use server" xml:space="preserve"> <source>Use server</source> <target>使用服务器</target> @@ -5383,6 +5531,10 @@ To connect, please ask your contact to create another connection link and check <target>查看安全码</target> <note>No comment provided by engineer.</note> </trans-unit> + <trans-unit id="Visible history" xml:space="preserve"> + <source>Visible history</source> + <note>chat feature</note> + </trans-unit> <trans-unit id="Voice messages" xml:space="preserve"> <source>Voice messages</source> <target>语音消息</target> @@ -5467,11 +5619,19 @@ To connect, please ask your contact to create another connection link and check <target>当您与某人共享隐身聊天资料时,该资料将用于他们邀请您加入的群组。</target> <note>No comment provided by engineer.</note> </trans-unit> + <trans-unit id="With encrypted files and media." xml:space="preserve"> + <source>With encrypted files and media.</source> + <note>No comment provided by engineer.</note> + </trans-unit> <trans-unit id="With optional welcome message." xml:space="preserve"> <source>With optional welcome message.</source> <target>带有可选的欢迎消息。</target> <note>No comment provided by engineer.</note> </trans-unit> + <trans-unit id="With reduced battery usage." xml:space="preserve"> + <source>With reduced battery usage.</source> + <note>No comment provided by engineer.</note> + </trans-unit> <trans-unit id="Wrong database passphrase" xml:space="preserve"> <source>Wrong database passphrase</source> <target>数据库密码错误</target> @@ -5556,11 +5716,6 @@ Repeat join request?</source> <target>您可以从锁屏上接听电话,无需设备和应用程序的认证。</target> <note>No comment provided by engineer.</note> </trans-unit> - <trans-unit id="You can also connect by clicking the link. If it opens in the browser, click **Open in mobile app** button." xml:space="preserve"> - <source>You can also connect by clicking the link. If it opens in the browser, click **Open in mobile app** button.</source> - <target>您也可以通过点击链接进行连接。如果在浏览器中打开,请点击“在移动应用程序中打开”按钮。</target> - <note>No comment provided by engineer.</note> - </trans-unit> <trans-unit id="You can create it later" xml:space="preserve"> <source>You can create it later</source> <target>您可以以后创建它</target> @@ -5581,6 +5736,10 @@ Repeat join request?</source> <target>您可以隐藏或静音用户个人资料——只需向右滑动。</target> <note>No comment provided by engineer.</note> </trans-unit> + <trans-unit id="You can make it visible to your SimpleX contacts via Settings." xml:space="preserve"> + <source>You can make it visible to your SimpleX contacts via Settings.</source> + <note>No comment provided by engineer.</note> + </trans-unit> <trans-unit id="You can now send messages to %@" xml:space="preserve"> <source>You can now send messages to %@</source> <target>您现在可以给 %@ 发送消息</target> @@ -5621,6 +5780,10 @@ Repeat join request?</source> <target>您可以使用 markdown 来编排消息格式:</target> <note>No comment provided by engineer.</note> </trans-unit> + <trans-unit id="You can view invitation link again in connection details." xml:space="preserve"> + <source>You can view invitation link again in connection details.</source> + <note>No comment provided by engineer.</note> + </trans-unit> <trans-unit id="You can't send messages!" xml:space="preserve"> <source>You can't send messages!</source> <target>您无法发送消息!</target> @@ -5805,13 +5968,6 @@ You can cancel this connection and remove the contact (and try later with a new <target>您的联系人可以允许完全删除消息。</target> <note>No comment provided by engineer.</note> </trans-unit> - <trans-unit id="Your contacts in SimpleX will see it. You can change it in Settings." xml:space="preserve"> - <source>Your contacts in SimpleX will see it. -You can change it in Settings.</source> - <target>您的 SimpleX 的联系人会看到它。 -您可以在设置中更改它。</target> - <note>No comment provided by engineer.</note> - </trans-unit> <trans-unit id="Your contacts will remain connected." xml:space="preserve"> <source>Your contacts will remain connected.</source> <target>与您的联系人保持连接。</target> @@ -5960,6 +6116,14 @@ SimpleX 服务器无法看到您的资料。</target> <source>blocked</source> <note>No comment provided by engineer.</note> </trans-unit> + <trans-unit id="blocked %@" xml:space="preserve"> + <source>blocked %@</source> + <note>rcv group event chat item</note> + </trans-unit> + <trans-unit id="blocked by admin" xml:space="preserve"> + <source>blocked by admin</source> + <note>blocked chat item</note> + </trans-unit> <trans-unit id="bold" xml:space="preserve"> <source>bold</source> <target>加粗</target> @@ -6080,6 +6244,10 @@ SimpleX 服务器无法看到您的资料。</target> <target>连接:%@</target> <note>connection information</note> </trans-unit> + <trans-unit id="contact %@ changed to %@" xml:space="preserve"> + <source>contact %1$@ changed to %2$@</source> + <note>profile update event chat item</note> + </trans-unit> <trans-unit id="contact has e2e encryption" xml:space="preserve"> <source>contact has e2e encryption</source> <target>联系人具有端到端加密</target> @@ -6349,6 +6517,10 @@ SimpleX 服务器无法看到您的资料。</target> <target>成员</target> <note>member role</note> </trans-unit> + <trans-unit id="member %@ changed to %@" xml:space="preserve"> + <source>member %1$@ changed to %2$@</source> + <note>profile update event chat item</note> + </trans-unit> <trans-unit id="member connected" xml:space="preserve"> <source>connected</source> <target>已连接</target> @@ -6471,6 +6643,14 @@ SimpleX 服务器无法看到您的资料。</target> <target>已删除 %@</target> <note>rcv group event chat item</note> </trans-unit> + <trans-unit id="removed contact address" xml:space="preserve"> + <source>removed contact address</source> + <note>profile update event chat item</note> + </trans-unit> + <trans-unit id="removed profile picture" xml:space="preserve"> + <source>removed profile picture</source> + <note>profile update event chat item</note> + </trans-unit> <trans-unit id="removed you" xml:space="preserve"> <source>removed you</source> <target>已将您移除</target> @@ -6501,6 +6681,14 @@ SimpleX 服务器无法看到您的资料。</target> <target>发送私信</target> <note>No comment provided by engineer.</note> </trans-unit> + <trans-unit id="set new contact address" xml:space="preserve"> + <source>set new contact address</source> + <note>profile update event chat item</note> + </trans-unit> + <trans-unit id="set new profile picture" xml:space="preserve"> + <source>set new profile picture</source> + <note>profile update event chat item</note> + </trans-unit> <trans-unit id="starting…" xml:space="preserve"> <source>starting…</source> <target>启动中……</target> @@ -6516,16 +6704,28 @@ SimpleX 服务器无法看到您的资料。</target> <target>这个联系人</target> <note>notification title</note> </trans-unit> + <trans-unit id="unblocked %@" xml:space="preserve"> + <source>unblocked %@</source> + <note>rcv group event chat item</note> + </trans-unit> <trans-unit id="unknown" xml:space="preserve"> <source>unknown</source> <target>未知</target> <note>connection info</note> </trans-unit> + <trans-unit id="unknown status" xml:space="preserve"> + <source>unknown status</source> + <note>No comment provided by engineer.</note> + </trans-unit> <trans-unit id="updated group profile" xml:space="preserve"> <source>updated group profile</source> <target>已更新的群组资料</target> <note>rcv group event chat item</note> </trans-unit> + <trans-unit id="updated profile" xml:space="preserve"> + <source>updated profile</source> + <note>profile update event chat item</note> + </trans-unit> <trans-unit id="v%@" xml:space="preserve"> <source>v%@</source> <note>No comment provided by engineer.</note> @@ -6595,6 +6795,10 @@ SimpleX 服务器无法看到您的资料。</target> <target>您是观察者</target> <note>No comment provided by engineer.</note> </trans-unit> + <trans-unit id="you blocked %@" xml:space="preserve"> + <source>you blocked %@</source> + <note>snd group event chat item</note> + </trans-unit> <trans-unit id="you changed address" xml:space="preserve"> <source>you changed address</source> <target>您已更改地址</target> @@ -6635,6 +6839,10 @@ SimpleX 服务器无法看到您的资料。</target> <target>您分享了一次性链接隐身聊天</target> <note>chat list item description</note> </trans-unit> + <trans-unit id="you unblocked %@" xml:space="preserve"> + <source>you unblocked %@</source> + <note>snd group event chat item</note> + </trans-unit> <trans-unit id="you: " xml:space="preserve"> <source>you: </source> <target>您: </target> diff --git a/apps/ios/SimpleX Localizations/zh-Hant.xcloc/Localized Contents/zh-Hant.xliff b/apps/ios/SimpleX Localizations/zh-Hant.xcloc/Localized Contents/zh-Hant.xliff index 821db2620f..03a108d112 100644 --- a/apps/ios/SimpleX Localizations/zh-Hant.xcloc/Localized Contents/zh-Hant.xliff +++ b/apps/ios/SimpleX Localizations/zh-Hant.xcloc/Localized Contents/zh-Hant.xliff @@ -5868,6 +5868,36 @@ It can happen because of some bug or when the connection is compromised.</source <target state="translated">你和你的聯絡人可以新增訊息互動。</target> <note>No comment provided by engineer.</note> </trans-unit> + <trans-unit id="%@ connected" xml:space="preserve" approved="no"> + <source>%@ connected</source> + <target state="translated">%@ 已連接</target> + <note>No comment provided by engineer.</note> + </trans-unit> + <trans-unit id="# %@" xml:space="preserve" approved="no"> + <source># %@</source> + <target state="translated"># %@</target> + <note>copied message info title, # <title></note> + </trans-unit> + <trans-unit id="%@ and %@" xml:space="preserve" approved="no"> + <source>%@ and %@</source> + <target state="translated">%@ 和 %@</target> + <note>No comment provided by engineer.</note> + </trans-unit> + <trans-unit id="## History" xml:space="preserve" approved="no"> + <source>## History</source> + <target state="translated">紀錄</target> + <note>copied message info</note> + </trans-unit> + <trans-unit id="## In reply to" xml:space="preserve" approved="no"> + <source>## In reply to</source> + <target state="translated">回覆</target> + <note>copied message info</note> + </trans-unit> + <trans-unit id="%@ and %@ connected" xml:space="preserve" approved="no"> + <source>%@ and %@ connected</source> + <target state="translated">%@ 和 %@ 已連接</target> + <note>No comment provided by engineer.</note> + </trans-unit> </body> </file> <file original="en.lproj/SimpleX--iOS--InfoPlist.strings" source-language="en" target-language="zh-Hant" datatype="plaintext"> diff --git a/apps/ios/SimpleX NSE/NotificationService.swift b/apps/ios/SimpleX NSE/NotificationService.swift index 1c34796ecc..61c439fb33 100644 --- a/apps/ios/SimpleX NSE/NotificationService.swift +++ b/apps/ios/SimpleX NSE/NotificationService.swift @@ -631,7 +631,7 @@ func receivedMsgNtf(_ res: ChatResponse) async -> (String, NSENotification)? { ntfBadgeCountGroupDefault.set(max(0, ntfBadgeCountGroupDefault.get() - 1)) } if let file = cItem.autoReceiveFile() { - cItem = autoReceiveFile(file, encrypted: cItem.encryptLocalFile) ?? cItem + cItem = autoReceiveFile(file) ?? cItem } let ntf: NSENotification = cInfo.ntfsEnabled ? .nse(createMessageReceivedNtf(user, cInfo, cItem)) : .empty return cItem.showNotification ? (aChatItem.chatId, ntf) : nil @@ -775,13 +775,16 @@ func apiSetFileToReceive(fileId: Int64, encrypted: Bool) { logger.error("setFileToReceive error: \(responseError(r))") } -func autoReceiveFile(_ file: CIFile, encrypted: Bool) -> ChatItem? { +func autoReceiveFile(_ file: CIFile) -> ChatItem? { + let encrypted = privacyEncryptLocalFilesGroupDefault.get() switch file.fileProtocol { case .smp: return apiReceiveFile(fileId: file.fileId, encrypted: encrypted)?.chatItem case .xftp: apiSetFileToReceive(fileId: file.fileId, encrypted: encrypted) return nil + case .local: + return nil } } diff --git a/apps/ios/SimpleX NSE/tr.lproj/InfoPlist.strings b/apps/ios/SimpleX NSE/tr.lproj/InfoPlist.strings new file mode 100644 index 0000000000..476da9ed91 --- /dev/null +++ b/apps/ios/SimpleX NSE/tr.lproj/InfoPlist.strings @@ -0,0 +1,9 @@ +/* Bundle display name */ +"CFBundleDisplayName" = "SimpleX NSE"; + +/* Bundle name */ +"CFBundleName" = "SimpleX NSE"; + +/* Copyright (human-readable) */ +"NSHumanReadableCopyright" = "Telif Hakkı © 2024 SimpleX Chat. Tüm hakları saklıdır."; + diff --git a/apps/ios/SimpleX.xcodeproj/project.pbxproj b/apps/ios/SimpleX.xcodeproj/project.pbxproj index c975d2fa1f..49b891ee82 100644 --- a/apps/ios/SimpleX.xcodeproj/project.pbxproj +++ b/apps/ios/SimpleX.xcodeproj/project.pbxproj @@ -16,7 +16,6 @@ 18415C6C56DBCEC2CBBD2F11 /* WebRTCClient.swift in Sources */ = {isa = PBXBuildFile; fileRef = 18415323A4082FC92887F906 /* WebRTCClient.swift */; }; 18415F9A2D551F9757DA4654 /* CIVideoView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 18415FD2E36F13F596A45BB4 /* CIVideoView.swift */; }; 18415FEFE153C5920BFB7828 /* GroupWelcomeView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1841516F0CE5992B0EDFB377 /* GroupWelcomeView.swift */; }; - 3C8C548928133C84000A3EC7 /* PasteToConnectView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3C8C548828133C84000A3EC7 /* PasteToConnectView.swift */; }; 3CDBCF4227FAE51000354CDD /* ComposeLinkView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3CDBCF4127FAE51000354CDD /* ComposeLinkView.swift */; }; 3CDBCF4827FF621E00354CDD /* CILinkView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3CDBCF4727FF621E00354CDD /* CILinkView.swift */; }; 5C00164428A26FBC0094D739 /* ContextMenu.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5C00164328A26FBC0094D739 /* ContextMenu.swift */; }; @@ -30,11 +29,6 @@ 5C116CDC27AABE0400E66D01 /* ContactRequestView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5C116CDB27AABE0400E66D01 /* ContactRequestView.swift */; }; 5C13730B28156D2700F43030 /* ContactConnectionView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5C13730A28156D2700F43030 /* ContactConnectionView.swift */; }; 5C1A4C1E27A715B700EAD5AD /* ChatItemView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5C1A4C1D27A715B700EAD5AD /* ChatItemView.swift */; }; - 5C245F232B4EAA5E001CC39F /* libgmpxx.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 5C245F1E2B4EAA5E001CC39F /* libgmpxx.a */; }; - 5C245F242B4EAA5E001CC39F /* libHSsimplex-chat-5.4.3.0-BrNBQIZf2Ju9TtaZoeJyIH-ghc9.6.3.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 5C245F1F2B4EAA5E001CC39F /* libHSsimplex-chat-5.4.3.0-BrNBQIZf2Ju9TtaZoeJyIH-ghc9.6.3.a */; }; - 5C245F252B4EAA5E001CC39F /* libgmp.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 5C245F202B4EAA5E001CC39F /* libgmp.a */; }; - 5C245F262B4EAA5E001CC39F /* libHSsimplex-chat-5.4.3.0-BrNBQIZf2Ju9TtaZoeJyIH.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 5C245F212B4EAA5E001CC39F /* libHSsimplex-chat-5.4.3.0-BrNBQIZf2Ju9TtaZoeJyIH.a */; }; - 5C245F272B4EAA5E001CC39F /* libffi.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 5C245F222B4EAA5E001CC39F /* libffi.a */; }; 5C2E260727A2941F00F70299 /* SimpleXAPI.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5C2E260627A2941F00F70299 /* SimpleXAPI.swift */; }; 5C2E260B27A30CFA00F70299 /* ChatListView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5C2E260A27A30CFA00F70299 /* ChatListView.swift */; }; 5C2E260F27A30FDC00F70299 /* ChatView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5C2E260E27A30FDC00F70299 /* ChatView.swift */; }; @@ -61,13 +55,17 @@ 5C5F2B7027EBC704006A9D5F /* ProfileImage.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5C5F2B6F27EBC704006A9D5F /* ProfileImage.swift */; }; 5C65DAF929D0CC20003CEE45 /* DeveloperView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5C65DAF829D0CC20003CEE45 /* DeveloperView.swift */; }; 5C65F343297D45E100B67AF3 /* VersionView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5C65F341297D3F3600B67AF3 /* VersionView.swift */; }; - 5C6AD81327A834E300348BD7 /* NewChatButton.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5C6AD81227A834E300348BD7 /* NewChatButton.swift */; }; 5C6BA667289BD954009B8ECC /* DismissSheets.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5C6BA666289BD954009B8ECC /* DismissSheets.swift */; }; 5C7031162953C97F00150A12 /* CIFeaturePreferenceView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5C7031152953C97F00150A12 /* CIFeaturePreferenceView.swift */; }; 5C7505A227B65FDB00BE3227 /* CIMetaView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5C7505A127B65FDB00BE3227 /* CIMetaView.swift */; }; 5C7505A527B679EE00BE3227 /* NavLinkPlain.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5C7505A427B679EE00BE3227 /* NavLinkPlain.swift */; }; 5C7505A827B6D34800BE3227 /* ChatInfoToolbar.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5C7505A727B6D34800BE3227 /* ChatInfoToolbar.swift */; }; 5C764E89279CBCB3000C6508 /* ChatModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5C764E88279CBCB3000C6508 /* ChatModel.swift */; }; + 5C83A1AD2B5EF67D00AE0A4A /* libgmp.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 5C83A1A82B5EF67D00AE0A4A /* libgmp.a */; }; + 5C83A1AE2B5EF67D00AE0A4A /* libHSsimplex-chat-5.5.0.4-HTW6wkBBAjO2GDtnvnI9O3-ghc9.6.3.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 5C83A1A92B5EF67D00AE0A4A /* libHSsimplex-chat-5.5.0.4-HTW6wkBBAjO2GDtnvnI9O3-ghc9.6.3.a */; }; + 5C83A1AF2B5EF67D00AE0A4A /* libHSsimplex-chat-5.5.0.4-HTW6wkBBAjO2GDtnvnI9O3.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 5C83A1AA2B5EF67D00AE0A4A /* libHSsimplex-chat-5.5.0.4-HTW6wkBBAjO2GDtnvnI9O3.a */; }; + 5C83A1B02B5EF67D00AE0A4A /* libffi.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 5C83A1AB2B5EF67D00AE0A4A /* libffi.a */; }; + 5C83A1B12B5EF67D00AE0A4A /* libgmpxx.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 5C83A1AC2B5EF67D00AE0A4A /* libgmpxx.a */; }; 5C8F01CD27A6F0D8007D2C8D /* CodeScanner in Frameworks */ = {isa = PBXBuildFile; productRef = 5C8F01CC27A6F0D8007D2C8D /* CodeScanner */; }; 5C93292F29239A170090FFF9 /* ProtocolServersView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5C93292E29239A170090FFF9 /* ProtocolServersView.swift */; }; 5C93293129239BED0090FFF9 /* ProtocolServerView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5C93293029239BED0090FFF9 /* ProtocolServerView.swift */; }; @@ -98,8 +96,6 @@ 5CB0BA92282713FD00B3292C /* CreateProfile.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5CB0BA91282713FD00B3292C /* CreateProfile.swift */; }; 5CB0BA9A2827FD8800B3292C /* HowItWorks.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5CB0BA992827FD8800B3292C /* HowItWorks.swift */; }; 5CB2084F28DA4B4800D024EC /* RTCServers.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5CB2084E28DA4B4800D024EC /* RTCServers.swift */; }; - 5CB2085128DB64CA00D024EC /* CreateLinkView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5CB2085028DB64CA00D024EC /* CreateLinkView.swift */; }; - 5CB2085328DB7CAF00D024EC /* ConnectViaLinkView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5CB2085228DB7CAF00D024EC /* ConnectViaLinkView.swift */; }; 5CB346E52868AA7F001FD2EF /* SuspendChat.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5CB346E42868AA7F001FD2EF /* SuspendChat.swift */; }; 5CB346E72868D76D001FD2EF /* NotificationsView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5CB346E62868D76D001FD2EF /* NotificationsView.swift */; }; 5CB346E92869E8BA001FD2EF /* PushEnvironment.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5CB346E82869E8BA001FD2EF /* PushEnvironment.swift */; }; @@ -121,8 +117,6 @@ 5CC2C0FF2809BF11000C35E3 /* SimpleX--iOS--InfoPlist.strings in Resources */ = {isa = PBXBuildFile; fileRef = 5CC2C0FD2809BF11000C35E3 /* SimpleX--iOS--InfoPlist.strings */; }; 5CC868F329EB540C0017BBFD /* CIRcvDecryptionError.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5CC868F229EB540C0017BBFD /* CIRcvDecryptionError.swift */; }; 5CCB939C297EFCB100399E78 /* NavStackCompat.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5CCB939B297EFCB100399E78 /* NavStackCompat.swift */; }; - 5CCD403427A5F6DF00368C90 /* AddContactView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5CCD403327A5F6DF00368C90 /* AddContactView.swift */; }; - 5CCD403727A5F9A200368C90 /* ScanToConnectView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5CCD403627A5F9A200368C90 /* ScanToConnectView.swift */; }; 5CD67B8F2B0E858A00C510B1 /* hs_init.h in Headers */ = {isa = PBXBuildFile; fileRef = 5CD67B8D2B0E858A00C510B1 /* hs_init.h */; settings = {ATTRIBUTES = (Public, ); }; }; 5CD67B902B0E858A00C510B1 /* hs_init.c in Sources */ = {isa = PBXBuildFile; fileRef = 5CD67B8E2B0E858A00C510B1 /* hs_init.c */; }; 5CDCAD482818589900503DA2 /* NotificationService.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5CDCAD472818589900503DA2 /* NotificationService.swift */; }; @@ -157,6 +151,8 @@ 5CFA59D12864782E00863A68 /* ChatArchiveView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5CFA59CF286477B400863A68 /* ChatArchiveView.swift */; }; 5CFE0921282EEAF60002594B /* ZoomableScrollView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5CFE0920282EEAF60002594B /* ZoomableScrollView.swift */; }; 5CFE0922282EEAF60002594B /* ZoomableScrollView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5CFE0920282EEAF60002594B /* ZoomableScrollView.swift */; }; + 640417CD2B29B8C200CCB412 /* NewChatMenuButton.swift in Sources */ = {isa = PBXBuildFile; fileRef = 640417CB2B29B8C200CCB412 /* NewChatMenuButton.swift */; }; + 640417CE2B29B8C200CCB412 /* NewChatView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 640417CC2B29B8C200CCB412 /* NewChatView.swift */; }; 6407BA83295DA85D0082BA18 /* CIInvalidJSONView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6407BA82295DA85D0082BA18 /* CIInvalidJSONView.swift */; }; 6419EC562AB8BC8B004A607A /* ContextInvitingContactMemberView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6419EC552AB8BC8B004A607A /* ContextInvitingContactMemberView.swift */; }; 6419EC582AB97507004A607A /* CIMemberCreatedContactView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6419EC572AB97507004A607A /* CIMemberCreatedContactView.swift */; }; @@ -268,7 +264,6 @@ 18415B08031E8FB0F7FC27F9 /* CallViewRenderers.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = CallViewRenderers.swift; sourceTree = "<group>"; }; 18415DAAAD1ADBEDB0EDA852 /* VideoPlayerView.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = VideoPlayerView.swift; sourceTree = "<group>"; }; 18415FD2E36F13F596A45BB4 /* CIVideoView.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = CIVideoView.swift; sourceTree = "<group>"; }; - 3C8C548828133C84000A3EC7 /* PasteToConnectView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PasteToConnectView.swift; sourceTree = "<group>"; }; 3CDBCF4127FAE51000354CDD /* ComposeLinkView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ComposeLinkView.swift; sourceTree = "<group>"; }; 3CDBCF4727FF621E00354CDD /* CILinkView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CILinkView.swift; sourceTree = "<group>"; }; 5C00164328A26FBC0094D739 /* ContextMenu.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ContextMenu.swift; sourceTree = "<group>"; }; @@ -285,11 +280,9 @@ 5C13730A28156D2700F43030 /* ContactConnectionView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ContactConnectionView.swift; sourceTree = "<group>"; }; 5C13730C2815740A00F43030 /* DebugJSON.playground */ = {isa = PBXFileReference; lastKnownFileType = file.playground; path = DebugJSON.playground; sourceTree = "<group>"; xcLanguageSpecificationIdentifier = xcode.lang.swift; }; 5C1A4C1D27A715B700EAD5AD /* ChatItemView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ChatItemView.swift; sourceTree = "<group>"; }; - 5C245F1E2B4EAA5E001CC39F /* libgmpxx.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; path = libgmpxx.a; sourceTree = "<group>"; }; - 5C245F1F2B4EAA5E001CC39F /* libHSsimplex-chat-5.4.3.0-BrNBQIZf2Ju9TtaZoeJyIH-ghc9.6.3.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; path = "libHSsimplex-chat-5.4.3.0-BrNBQIZf2Ju9TtaZoeJyIH-ghc9.6.3.a"; sourceTree = "<group>"; }; - 5C245F202B4EAA5E001CC39F /* libgmp.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; path = libgmp.a; sourceTree = "<group>"; }; - 5C245F212B4EAA5E001CC39F /* libHSsimplex-chat-5.4.3.0-BrNBQIZf2Ju9TtaZoeJyIH.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; path = "libHSsimplex-chat-5.4.3.0-BrNBQIZf2Ju9TtaZoeJyIH.a"; sourceTree = "<group>"; }; - 5C245F222B4EAA5E001CC39F /* libffi.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; path = libffi.a; sourceTree = "<group>"; }; + 5C245F3C2B501E98001CC39F /* tr */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = tr; path = tr.lproj/Localizable.strings; sourceTree = "<group>"; }; + 5C245F3D2B501F13001CC39F /* tr */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = tr; path = "tr.lproj/SimpleX--iOS--InfoPlist.strings"; sourceTree = "<group>"; }; + 5C245F3E2B501F13001CC39F /* tr */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = tr; path = tr.lproj/InfoPlist.strings; sourceTree = "<group>"; }; 5C2E260627A2941F00F70299 /* SimpleXAPI.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SimpleXAPI.swift; sourceTree = "<group>"; }; 5C2E260A27A30CFA00F70299 /* ChatListView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ChatListView.swift; sourceTree = "<group>"; }; 5C2E260E27A30FDC00F70299 /* ChatView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ChatView.swift; sourceTree = "<group>"; }; @@ -329,7 +322,6 @@ 5C65DAED29CB8908003CEE45 /* es */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = es; path = es.lproj/InfoPlist.strings; sourceTree = "<group>"; }; 5C65DAF829D0CC20003CEE45 /* DeveloperView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DeveloperView.swift; sourceTree = "<group>"; }; 5C65F341297D3F3600B67AF3 /* VersionView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = VersionView.swift; sourceTree = "<group>"; }; - 5C6AD81227A834E300348BD7 /* NewChatButton.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NewChatButton.swift; sourceTree = "<group>"; }; 5C6BA666289BD954009B8ECC /* DismissSheets.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DismissSheets.swift; sourceTree = "<group>"; }; 5C6D183229E93FBA00D430B3 /* pl */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = pl; path = "pl.lproj/SimpleX--iOS--InfoPlist.strings"; sourceTree = "<group>"; }; 5C6D183329E93FBA00D430B3 /* pl */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = pl; path = pl.lproj/InfoPlist.strings; sourceTree = "<group>"; }; @@ -338,6 +330,11 @@ 5C7505A427B679EE00BE3227 /* NavLinkPlain.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NavLinkPlain.swift; sourceTree = "<group>"; }; 5C7505A727B6D34800BE3227 /* ChatInfoToolbar.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ChatInfoToolbar.swift; sourceTree = "<group>"; }; 5C764E88279CBCB3000C6508 /* ChatModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ChatModel.swift; sourceTree = "<group>"; }; + 5C83A1A82B5EF67D00AE0A4A /* libgmp.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; path = libgmp.a; sourceTree = "<group>"; }; + 5C83A1A92B5EF67D00AE0A4A /* libHSsimplex-chat-5.5.0.4-HTW6wkBBAjO2GDtnvnI9O3-ghc9.6.3.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; path = "libHSsimplex-chat-5.5.0.4-HTW6wkBBAjO2GDtnvnI9O3-ghc9.6.3.a"; sourceTree = "<group>"; }; + 5C83A1AA2B5EF67D00AE0A4A /* libHSsimplex-chat-5.5.0.4-HTW6wkBBAjO2GDtnvnI9O3.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; path = "libHSsimplex-chat-5.5.0.4-HTW6wkBBAjO2GDtnvnI9O3.a"; sourceTree = "<group>"; }; + 5C83A1AB2B5EF67D00AE0A4A /* libffi.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; path = libffi.a; sourceTree = "<group>"; }; + 5C83A1AC2B5EF67D00AE0A4A /* libgmpxx.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; path = libgmpxx.a; sourceTree = "<group>"; }; 5C84FE9129A216C800D95B1A /* nl */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = nl; path = nl.lproj/Localizable.strings; sourceTree = "<group>"; }; 5C84FE9329A2179C00D95B1A /* nl */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = nl; path = "nl.lproj/SimpleX--iOS--InfoPlist.strings"; sourceTree = "<group>"; }; 5C84FE9429A2179C00D95B1A /* nl */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = nl; path = nl.lproj/InfoPlist.strings; sourceTree = "<group>"; }; @@ -386,8 +383,6 @@ 5CB0BA91282713FD00B3292C /* CreateProfile.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CreateProfile.swift; sourceTree = "<group>"; }; 5CB0BA992827FD8800B3292C /* HowItWorks.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = HowItWorks.swift; sourceTree = "<group>"; }; 5CB2084E28DA4B4800D024EC /* RTCServers.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RTCServers.swift; sourceTree = "<group>"; }; - 5CB2085028DB64CA00D024EC /* CreateLinkView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CreateLinkView.swift; sourceTree = "<group>"; }; - 5CB2085228DB7CAF00D024EC /* ConnectViaLinkView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ConnectViaLinkView.swift; sourceTree = "<group>"; }; 5CB2085428DE647400D024EC /* de */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = de; path = de.lproj/Localizable.strings; sourceTree = "<group>"; }; 5CB346E42868AA7F001FD2EF /* SuspendChat.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SuspendChat.swift; sourceTree = "<group>"; }; 5CB346E62868D76D001FD2EF /* NotificationsView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NotificationsView.swift; sourceTree = "<group>"; }; @@ -413,8 +408,6 @@ 5CC2C0FE2809BF11000C35E3 /* ru */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = ru; path = "ru.lproj/SimpleX--iOS--InfoPlist.strings"; sourceTree = "<group>"; }; 5CC868F229EB540C0017BBFD /* CIRcvDecryptionError.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CIRcvDecryptionError.swift; sourceTree = "<group>"; }; 5CCB939B297EFCB100399E78 /* NavStackCompat.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NavStackCompat.swift; sourceTree = "<group>"; }; - 5CCD403327A5F6DF00368C90 /* AddContactView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AddContactView.swift; sourceTree = "<group>"; }; - 5CCD403627A5F9A200368C90 /* ScanToConnectView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ScanToConnectView.swift; sourceTree = "<group>"; }; 5CD67B8D2B0E858A00C510B1 /* hs_init.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = hs_init.h; sourceTree = "<group>"; }; 5CD67B8E2B0E858A00C510B1 /* hs_init.c */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.c; path = hs_init.c; sourceTree = "<group>"; }; 5CDCAD452818589900503DA2 /* SimpleX NSE.appex */ = {isa = PBXFileReference; explicitFileType = "wrapper.app-extension"; includeInIndex = 0; path = "SimpleX NSE.appex"; sourceTree = BUILT_PRODUCTS_DIR; }; @@ -449,6 +442,8 @@ 5CFA59C32860BC6200863A68 /* MigrateToAppGroupView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MigrateToAppGroupView.swift; sourceTree = "<group>"; }; 5CFA59CF286477B400863A68 /* ChatArchiveView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ChatArchiveView.swift; sourceTree = "<group>"; }; 5CFE0920282EEAF60002594B /* ZoomableScrollView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; name = ZoomableScrollView.swift; path = Shared/Views/ZoomableScrollView.swift; sourceTree = SOURCE_ROOT; }; + 640417CB2B29B8C200CCB412 /* NewChatMenuButton.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = NewChatMenuButton.swift; sourceTree = "<group>"; }; + 640417CC2B29B8C200CCB412 /* NewChatView.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = NewChatView.swift; sourceTree = "<group>"; }; 6407BA82295DA85D0082BA18 /* CIInvalidJSONView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CIInvalidJSONView.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>"; }; @@ -529,13 +524,13 @@ isa = PBXFrameworksBuildPhase; buildActionMask = 2147483647; files = ( - 5C245F232B4EAA5E001CC39F /* libgmpxx.a in Frameworks */, - 5C245F262B4EAA5E001CC39F /* libHSsimplex-chat-5.4.3.0-BrNBQIZf2Ju9TtaZoeJyIH.a in Frameworks */, - 5C245F252B4EAA5E001CC39F /* libgmp.a in Frameworks */, 5CE2BA93284534B000EC33A6 /* libiconv.tbd in Frameworks */, - 5C245F272B4EAA5E001CC39F /* libffi.a in Frameworks */, + 5C83A1B02B5EF67D00AE0A4A /* libffi.a in Frameworks */, + 5C83A1AD2B5EF67D00AE0A4A /* libgmp.a in Frameworks */, + 5C83A1AE2B5EF67D00AE0A4A /* libHSsimplex-chat-5.5.0.4-HTW6wkBBAjO2GDtnvnI9O3-ghc9.6.3.a in Frameworks */, + 5C83A1AF2B5EF67D00AE0A4A /* libHSsimplex-chat-5.5.0.4-HTW6wkBBAjO2GDtnvnI9O3.a in Frameworks */, 5CE2BA94284534BB00EC33A6 /* libz.tbd in Frameworks */, - 5C245F242B4EAA5E001CC39F /* libHSsimplex-chat-5.4.3.0-BrNBQIZf2Ju9TtaZoeJyIH-ghc9.6.3.a in Frameworks */, + 5C83A1B12B5EF67D00AE0A4A /* libgmpxx.a in Frameworks */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -597,11 +592,11 @@ 5C764E5C279C70B7000C6508 /* Libraries */ = { isa = PBXGroup; children = ( - 5C245F222B4EAA5E001CC39F /* libffi.a */, - 5C245F202B4EAA5E001CC39F /* libgmp.a */, - 5C245F1E2B4EAA5E001CC39F /* libgmpxx.a */, - 5C245F1F2B4EAA5E001CC39F /* libHSsimplex-chat-5.4.3.0-BrNBQIZf2Ju9TtaZoeJyIH-ghc9.6.3.a */, - 5C245F212B4EAA5E001CC39F /* libHSsimplex-chat-5.4.3.0-BrNBQIZf2Ju9TtaZoeJyIH.a */, + 5C83A1AB2B5EF67D00AE0A4A /* libffi.a */, + 5C83A1A82B5EF67D00AE0A4A /* libgmp.a */, + 5C83A1AC2B5EF67D00AE0A4A /* libgmpxx.a */, + 5C83A1A92B5EF67D00AE0A4A /* libHSsimplex-chat-5.5.0.4-HTW6wkBBAjO2GDtnvnI9O3-ghc9.6.3.a */, + 5C83A1AA2B5EF67D00AE0A4A /* libHSsimplex-chat-5.5.0.4-HTW6wkBBAjO2GDtnvnI9O3.a */, ); path = Libraries; sourceTree = "<group>"; @@ -747,14 +742,10 @@ 5CB924DD27A8622200ACCCDD /* NewChat */ = { isa = PBXGroup; children = ( - 5C6AD81227A834E300348BD7 /* NewChatButton.swift */, - 5CCD403327A5F6DF00368C90 /* AddContactView.swift */, - 5CCD403627A5F9A200368C90 /* ScanToConnectView.swift */, - 3C8C548828133C84000A3EC7 /* PasteToConnectView.swift */, + 640417CB2B29B8C200CCB412 /* NewChatMenuButton.swift */, + 640417CC2B29B8C200CCB412 /* NewChatView.swift */, 5CC1C99127A6C7F5000D9FF6 /* QRCode.swift */, 6442E0B9287F169300CEC0F9 /* AddGroupView.swift */, - 5CB2085028DB64CA00D024EC /* CreateLinkView.swift */, - 5CB2085228DB7CAF00D024EC /* ConnectViaLinkView.swift */, 64D0C2C529FAC1EC00B38D5F /* AddContactLearnMore.swift */, ); path = NewChat; @@ -1061,6 +1052,7 @@ fi, uk, bg, + tr, ); mainGroup = 5CA059BD279559F40002BEB4; packageReferences = ( @@ -1123,8 +1115,8 @@ buildActionMask = 2147483647; files = ( 64C06EB52A0A4A7C00792D4D /* ChatItemInfoView.swift in Sources */, + 640417CE2B29B8C200CCB412 /* NewChatView.swift in Sources */, 6440CA03288AECA70062C672 /* AddGroupMembersView.swift in Sources */, - 5C6AD81327A834E300348BD7 /* NewChatButton.swift in Sources */, 5C3F1D58284363C400EC8A82 /* PrivacySettings.swift in Sources */, 5C55A923283CEDE600C4E99E /* SoundPlayer.swift in Sources */, 5C93292F29239A170090FFF9 /* ProtocolServersView.swift in Sources */, @@ -1171,13 +1163,11 @@ 5C063D2727A4564100AEC577 /* ChatPreviewView.swift in Sources */, 5CC868F329EB540C0017BBFD /* CIRcvDecryptionError.swift in Sources */, 5C35CFCB27B2E91D00FB6C6D /* NtfManager.swift in Sources */, - 3C8C548928133C84000A3EC7 /* PasteToConnectView.swift in Sources */, 5C9D13A3282187BB00AB8B43 /* WebRTC.swift in Sources */, 5C9A5BDB2871E05400A5B906 /* SetNotificationsMode.swift in Sources */, 5CB0BA8E2827126500B3292C /* OnboardingView.swift in Sources */, 6442E0BE2880182D00CEC0F9 /* GroupChatInfoView.swift in Sources */, 5C2E261227A30FEA00F70299 /* TerminalView.swift in Sources */, - 5CB2085128DB64CA00D024EC /* CreateLinkView.swift in Sources */, 5C9FD96E27A5D6ED0075386C /* SendMessageView.swift in Sources */, 5CA7DFC329302AF000F7FDDE /* AppSheet.swift in Sources */, 64E972072881BB22008DBC02 /* CIGroupInvitationView.swift in Sources */, @@ -1186,8 +1176,8 @@ 5CB9250D27A9432000ACCCDD /* ChatListNavLink.swift in Sources */, 649BCDA0280460FD00C3A862 /* ComposeImageView.swift in Sources */, 5CA059ED279559F40002BEB4 /* ContentView.swift in Sources */, - 5CCD403427A5F6DF00368C90 /* AddContactView.swift in Sources */, 5C05DF532840AA1D00C683F9 /* CallSettings.swift in Sources */, + 640417CD2B29B8C200CCB412 /* NewChatMenuButton.swift in Sources */, 5CFE0921282EEAF60002594B /* ZoomableScrollView.swift in Sources */, 5C3A88CE27DF50170060F1C2 /* DetermineWidth.swift in Sources */, 5C7505A527B679EE00BE3227 /* NavLinkPlain.swift in Sources */, @@ -1222,7 +1212,6 @@ 6448BBB628FA9D56000D2AB9 /* GroupLinkView.swift in Sources */, 5CB346E92869E8BA001FD2EF /* PushEnvironment.swift in Sources */, 5C55A91F283AD0E400C4E99E /* CallManager.swift in Sources */, - 5CCD403727A5F9A200368C90 /* ScanToConnectView.swift in Sources */, 5CFA59D12864782E00863A68 /* ChatArchiveView.swift in Sources */, 649BCDA22805D6EF00C3A862 /* CIImageView.swift in Sources */, 8C05382E2B39887E006436DC /* VideoUtils.swift in Sources */, @@ -1245,7 +1234,6 @@ 5C93293F2928E0FD0090FFF9 /* AudioRecPlay.swift in Sources */, 5C029EA82837DBB3004A9677 /* CICallItemView.swift in Sources */, 5CE4407227ADB1D0007B033A /* Emoji.swift in Sources */, - 5CB2085328DB7CAF00D024EC /* ConnectViaLinkView.swift in Sources */, 5C9CC7A928C532AB00BEF955 /* DatabaseErrorView.swift in Sources */, 5C1A4C1E27A715B700EAD5AD /* ChatItemView.swift in Sources */, 64AA1C6927EE10C800AC7277 /* ContextItemView.swift in Sources */, @@ -1352,6 +1340,7 @@ 5C136D8F2AAB3D14006DE2FC /* fi */, 5C636F672AAB3D2400751C84 /* uk */, 5C5B67932ABAF56000DA9412 /* bg */, + 5C245F3E2B501F13001CC39F /* tr */, ); name = InfoPlist.strings; sourceTree = "<group>"; @@ -1374,6 +1363,7 @@ 5CE6C7B32AAB1515007F345C /* fi */, 5CE6C7B42AAB1527007F345C /* uk */, 5C5B67912ABAF4B500DA9412 /* bg */, + 5C245F3C2B501E98001CC39F /* tr */, ); name = Localizable.strings; sourceTree = "<group>"; @@ -1395,6 +1385,7 @@ 5C136D8E2AAB3D14006DE2FC /* fi */, 5C636F662AAB3D2400751C84 /* uk */, 5C5B67922ABAF56000DA9412 /* bg */, + 5C245F3D2B501F13001CC39F /* tr */, ); name = "SimpleX--iOS--InfoPlist.strings"; sourceTree = "<group>"; @@ -1528,7 +1519,7 @@ CLANG_ENABLE_MODULES = YES; CODE_SIGN_ENTITLEMENTS = "SimpleX (iOS).entitlements"; CODE_SIGN_STYLE = Automatic; - CURRENT_PROJECT_VERSION = 188; + CURRENT_PROJECT_VERSION = 194; DEVELOPMENT_TEAM = 5NN7GUYB6T; ENABLE_BITCODE = NO; ENABLE_PREVIEWS = YES; @@ -1550,7 +1541,7 @@ "$(inherited)", "@executable_path/Frameworks", ); - MARKETING_VERSION = 5.4.3; + MARKETING_VERSION = 5.5; PRODUCT_BUNDLE_IDENTIFIER = chat.simplex.app; PRODUCT_NAME = SimpleX; SDKROOT = iphoneos; @@ -1571,7 +1562,7 @@ CLANG_ENABLE_MODULES = YES; CODE_SIGN_ENTITLEMENTS = "SimpleX (iOS).entitlements"; CODE_SIGN_STYLE = Automatic; - CURRENT_PROJECT_VERSION = 188; + CURRENT_PROJECT_VERSION = 194; DEVELOPMENT_TEAM = 5NN7GUYB6T; ENABLE_BITCODE = NO; ENABLE_PREVIEWS = YES; @@ -1593,7 +1584,7 @@ "$(inherited)", "@executable_path/Frameworks", ); - MARKETING_VERSION = 5.4.3; + MARKETING_VERSION = 5.5; PRODUCT_BUNDLE_IDENTIFIER = chat.simplex.app; PRODUCT_NAME = SimpleX; SDKROOT = iphoneos; @@ -1652,7 +1643,7 @@ CODE_SIGN_ENTITLEMENTS = "SimpleX NSE/SimpleX NSE.entitlements"; CODE_SIGN_IDENTITY = "Apple Development"; CODE_SIGN_STYLE = Automatic; - CURRENT_PROJECT_VERSION = 188; + CURRENT_PROJECT_VERSION = 194; DEVELOPMENT_TEAM = 5NN7GUYB6T; ENABLE_BITCODE = NO; GENERATE_INFOPLIST_FILE = YES; @@ -1665,7 +1656,7 @@ "@executable_path/Frameworks", "@executable_path/../../Frameworks", ); - MARKETING_VERSION = 5.4.3; + MARKETING_VERSION = 5.5; PRODUCT_BUNDLE_IDENTIFIER = "chat.simplex.app.SimpleX-NSE"; PRODUCT_NAME = "$(TARGET_NAME)"; PROVISIONING_PROFILE_SPECIFIER = ""; @@ -1684,7 +1675,7 @@ CODE_SIGN_ENTITLEMENTS = "SimpleX NSE/SimpleX NSE.entitlements"; CODE_SIGN_IDENTITY = "Apple Development"; CODE_SIGN_STYLE = Automatic; - CURRENT_PROJECT_VERSION = 188; + CURRENT_PROJECT_VERSION = 194; DEVELOPMENT_TEAM = 5NN7GUYB6T; ENABLE_BITCODE = NO; GENERATE_INFOPLIST_FILE = YES; @@ -1697,7 +1688,7 @@ "@executable_path/Frameworks", "@executable_path/../../Frameworks", ); - MARKETING_VERSION = 5.4.3; + MARKETING_VERSION = 5.5; PRODUCT_BUNDLE_IDENTIFIER = "chat.simplex.app.SimpleX-NSE"; PRODUCT_NAME = "$(TARGET_NAME)"; PROVISIONING_PROFILE_SPECIFIER = ""; @@ -1716,7 +1707,7 @@ APPLICATION_EXTENSION_API_ONLY = YES; CLANG_ENABLE_MODULES = YES; CODE_SIGN_STYLE = Automatic; - CURRENT_PROJECT_VERSION = 188; + CURRENT_PROJECT_VERSION = 194; DEFINES_MODULE = YES; DEVELOPMENT_TEAM = 5NN7GUYB6T; DYLIB_COMPATIBILITY_VERSION = 1; @@ -1740,7 +1731,7 @@ "$(inherited)", "$(PROJECT_DIR)/Libraries/sim", ); - MARKETING_VERSION = 5.4.3; + MARKETING_VERSION = 5.5; PRODUCT_BUNDLE_IDENTIFIER = chat.simplex.SimpleXChat; PRODUCT_NAME = "$(TARGET_NAME:c99extidentifier)"; SDKROOT = iphoneos; @@ -1762,7 +1753,7 @@ APPLICATION_EXTENSION_API_ONLY = YES; CLANG_ENABLE_MODULES = YES; CODE_SIGN_STYLE = Automatic; - CURRENT_PROJECT_VERSION = 188; + CURRENT_PROJECT_VERSION = 194; DEFINES_MODULE = YES; DEVELOPMENT_TEAM = 5NN7GUYB6T; DYLIB_COMPATIBILITY_VERSION = 1; @@ -1786,7 +1777,7 @@ "$(inherited)", "$(PROJECT_DIR)/Libraries/sim", ); - MARKETING_VERSION = 5.4.3; + MARKETING_VERSION = 5.5; PRODUCT_BUNDLE_IDENTIFIER = chat.simplex.SimpleXChat; PRODUCT_NAME = "$(TARGET_NAME:c99extidentifier)"; SDKROOT = iphoneos; diff --git a/apps/ios/SimpleXChat/APITypes.swift b/apps/ios/SimpleXChat/APITypes.swift index 411a1ab9cf..ae091f8415 100644 --- a/apps/ios/SimpleXChat/APITypes.swift +++ b/apps/ios/SimpleXChat/APITypes.swift @@ -41,6 +41,7 @@ public enum ChatCommand { case apiGetChat(type: ChatType, id: Int64, pagination: ChatPagination, search: String) case apiGetChatItemInfo(type: ChatType, id: Int64, itemId: Int64) case apiSendMessage(type: ChatType, id: Int64, file: CryptoFile?, quotedItemId: Int64?, msg: MsgContent, live: Bool, ttl: Int?) + case apiCreateChatItem(noteFolderId: Int64, file: CryptoFile?, msg: MsgContent) case apiUpdateChatItem(type: ChatType, id: Int64, itemId: Int64, msg: MsgContent, live: Bool) case apiDeleteChatItem(type: ChatType, id: Int64, itemId: Int64, mode: CIDeleteMode) case apiDeleteMemberChatItem(groupId: Int64, groupMemberId: Int64, itemId: Int64) @@ -54,6 +55,7 @@ public enum ChatCommand { case apiAddMember(groupId: Int64, contactId: Int64, memberRole: GroupMemberRole) case apiJoinGroup(groupId: Int64) case apiMemberRole(groupId: Int64, memberId: Int64, memberRole: GroupMemberRole) + case apiBlockMemberForAll(groupId: Int64, memberId: Int64, blocked: Bool) case apiRemoveMember(groupId: Int64, memberId: Int64) case apiLeaveGroup(groupId: Int64) case apiListMembers(groupId: Int64) @@ -178,6 +180,9 @@ public enum ChatCommand { let msg = encodeJSON(ComposedMessage(fileSource: file, quotedItemId: quotedItemId, msgContent: mc)) let ttlStr = ttl != nil ? "\(ttl!)" : "default" return "/_send \(ref(type, id)) live=\(onOff(live)) ttl=\(ttlStr) json \(msg)" + case let .apiCreateChatItem(noteFolderId, file, mc): + let msg = encodeJSON(ComposedMessage(fileSource: file, msgContent: mc)) + return "/_create *\(noteFolderId) json \(msg)" case let .apiUpdateChatItem(type, id, itemId, mc, live): return "/_update item \(ref(type, id)) \(itemId) live=\(onOff(live)) \(mc.cmdString)" case let .apiDeleteChatItem(type, id, itemId, mode): return "/_delete item \(ref(type, id)) \(itemId) \(mode.rawValue)" case let .apiDeleteMemberChatItem(groupId, groupMemberId, itemId): return "/_delete member item #\(groupId) \(groupMemberId) \(itemId)" @@ -191,6 +196,7 @@ public enum ChatCommand { case let .apiAddMember(groupId, contactId, memberRole): return "/_add #\(groupId) \(contactId) \(memberRole)" case let .apiJoinGroup(groupId): return "/_join #\(groupId)" case let .apiMemberRole(groupId, memberId, memberRole): return "/_member role #\(groupId) \(memberId) \(memberRole.rawValue)" + case let .apiBlockMemberForAll(groupId, memberId, blocked): return "/_block #\(groupId) \(memberId) blocked=\(onOff(blocked))" case let .apiRemoveMember(groupId, memberId): return "/_remove #\(groupId) \(memberId)" case let .apiLeaveGroup(groupId): return "/_leave #\(groupId)" case let .apiListMembers(groupId): return "/_members #\(groupId)" @@ -315,6 +321,7 @@ public enum ChatCommand { case .apiGetChat: return "apiGetChat" case .apiGetChatItemInfo: return "apiGetChatItemInfo" case .apiSendMessage: return "apiSendMessage" + case .apiCreateChatItem: return "apiCreateChatItem" case .apiUpdateChatItem: return "apiUpdateChatItem" case .apiDeleteChatItem: return "apiDeleteChatItem" case .apiConnectContactViaAddress: return "apiConnectContactViaAddress" @@ -329,6 +336,7 @@ public enum ChatCommand { case .apiAddMember: return "apiAddMember" case .apiJoinGroup: return "apiJoinGroup" case .apiMemberRole: return "apiMemberRole" + case .apiBlockMemberForAll: return "apiBlockMemberForAll" case .apiRemoveMember: return "apiRemoveMember" case .apiLeaveGroup: return "apiLeaveGroup" case .apiListMembers: return "apiListMembers" @@ -561,6 +569,8 @@ public enum ChatResponse: Decodable, Error { case joinedGroupMemberConnecting(user: UserRef, groupInfo: GroupInfo, hostMember: GroupMember, member: GroupMember) case memberRole(user: UserRef, groupInfo: GroupInfo, byMember: GroupMember, member: GroupMember, fromRole: GroupMemberRole, toRole: GroupMemberRole) case memberRoleUser(user: UserRef, groupInfo: GroupInfo, member: GroupMember, fromRole: GroupMemberRole, toRole: GroupMemberRole) + case memberBlockedForAll(user: UserRef, groupInfo: GroupInfo, byMember: GroupMember, member: GroupMember, blocked: Bool) + case memberBlockedForAllUser(user: UserRef, groupInfo: GroupInfo, member: GroupMember, blocked: Bool) case deletedMemberUser(user: UserRef, groupInfo: GroupInfo, member: GroupMember) case deletedMember(user: UserRef, groupInfo: GroupInfo, byMember: GroupMember, deletedMember: GroupMember) case leftMember(user: UserRef, groupInfo: GroupInfo, member: GroupMember) @@ -711,6 +721,8 @@ public enum ChatResponse: Decodable, Error { case .joinedGroupMemberConnecting: return "joinedGroupMemberConnecting" case .memberRole: return "memberRole" case .memberRoleUser: return "memberRoleUser" + case .memberBlockedForAll: return "memberBlockedForAll" + case .memberBlockedForAllUser: return "memberBlockedForAllUser" case .deletedMemberUser: return "deletedMemberUser" case .deletedMember: return "deletedMember" case .leftMember: return "leftMember" @@ -859,6 +871,8 @@ public enum ChatResponse: Decodable, Error { case let .joinedGroupMemberConnecting(u, groupInfo, hostMember, member): return withUser(u, "groupInfo: \(groupInfo)\nhostMember: \(hostMember)\nmember: \(member)") case let .memberRole(u, groupInfo, byMember, member, fromRole, toRole): return withUser(u, "groupInfo: \(groupInfo)\nbyMember: \(byMember)\nmember: \(member)\nfromRole: \(fromRole)\ntoRole: \(toRole)") case let .memberRoleUser(u, groupInfo, member, fromRole, toRole): return withUser(u, "groupInfo: \(groupInfo)\nmember: \(member)\nfromRole: \(fromRole)\ntoRole: \(toRole)") + case let .memberBlockedForAll(u, groupInfo, byMember, member, blocked): return withUser(u, "groupInfo: \(groupInfo)\nbyMember: \(byMember)\nmember: \(member)\nblocked: \(blocked)") + case let .memberBlockedForAllUser(u, groupInfo, member, blocked): return withUser(u, "groupInfo: \(groupInfo)\nmember: \(member)\nblocked: \(blocked)") case let .deletedMemberUser(u, groupInfo, member): return withUser(u, "groupInfo: \(groupInfo)\nmember: \(member)") case let .deletedMember(u, groupInfo, byMember, deletedMember): return withUser(u, "groupInfo: \(groupInfo)\nbyMember: \(byMember)\ndeletedMember: \(deletedMember)") case let .leftMember(u, groupInfo, member): return withUser(u, "groupInfo: \(groupInfo)\nmember: \(member)") @@ -1610,6 +1624,7 @@ public enum ChatErrorType: Decodable { case userUnknown case activeUserExists case userExists + case invalidDisplayName case differentActiveUser(commandUserId: Int64, activeUserId: Int64) case cantDeleteActiveUser(userId: Int64) case cantDeleteLastUser(userId: Int64) diff --git a/apps/ios/SimpleXChat/ChatTypes.swift b/apps/ios/SimpleXChat/ChatTypes.swift index a545d3508c..ff61a51d3e 100644 --- a/apps/ios/SimpleXChat/ChatTypes.swift +++ b/apps/ios/SimpleXChat/ChatTypes.swift @@ -172,7 +172,6 @@ public func fromLocalProfile (_ profile: LocalProfile) -> Profile { } public struct UserProfileUpdateSummary: Decodable { - public var notChanged: Int public var updateSuccesses: Int public var updateFailures: Int public var changedContacts: [Contact] @@ -181,6 +180,7 @@ public struct UserProfileUpdateSummary: Decodable { public enum ChatType: String { case direct = "@" case group = "#" + case local = "*" case contactRequest = "<@" case contactConnection = ":" } @@ -616,8 +616,8 @@ public enum ChatFeature: String, Decodable, Feature { } case .fullDelete: switch allowed { - case .always: return "Allow your contacts to irreversibly delete sent messages." - case .yes: return "Allow irreversible message deletion only if your contact allows it to you." + case .always: return "Allow your contacts to irreversibly delete sent messages. (24 hours)" + case .yes: return "Allow irreversible message deletion only if your contact allows it to you. (24 hours)" case .no: return "Contacts can mark messages for deletion; you will be able to view them." } case .reactions: @@ -653,11 +653,11 @@ public enum ChatFeature: String, Decodable, Feature { : "Disappearing messages are prohibited in this chat." case .fullDelete: return enabled.forUser && enabled.forContact - ? "Both you and your contact can irreversibly delete sent messages." + ? "Both you and your contact can irreversibly delete sent messages. (24 hours)" : enabled.forUser - ? "Only you can irreversibly delete messages (your contact can mark them for deletion)." + ? "Only you can irreversibly delete messages (your contact can mark them for deletion). (24 hours)" : enabled.forContact - ? "Only your contact can irreversibly delete messages (you can mark them for deletion)." + ? "Only your contact can irreversibly delete messages (you can mark them for deletion). (24 hours)" : "Irreversible message deletion is prohibited in this chat." case .reactions: return enabled.forUser && enabled.forContact @@ -694,6 +694,7 @@ public enum GroupFeature: String, Decodable, Feature { case reactions case voice case files + case history public var id: Self { self } @@ -712,6 +713,7 @@ public enum GroupFeature: String, Decodable, Feature { case .reactions: return NSLocalizedString("Message reactions", comment: "chat feature") case .voice: return NSLocalizedString("Voice messages", comment: "chat feature") case .files: return NSLocalizedString("Files and media", comment: "chat feature") + case .history: return NSLocalizedString("Visible history", comment: "chat feature") } } @@ -723,6 +725,7 @@ public enum GroupFeature: String, Decodable, Feature { case .reactions: return "face.smiling" case .voice: return "mic" case .files: return "doc" + case .history: return "clock" } } @@ -734,6 +737,7 @@ public enum GroupFeature: String, Decodable, Feature { case .reactions: return "face.smiling.fill" case .voice: return "mic.fill" case .files: return "doc.fill" + case .history: return "clock.fill" } } @@ -759,7 +763,7 @@ public enum GroupFeature: String, Decodable, Feature { } case .fullDelete: switch enabled { - case .on: return "Allow to irreversibly delete sent messages." + case .on: return "Allow to irreversibly delete sent messages. (24 hours)" case .off: return "Prohibit irreversible message deletion." } case .reactions: @@ -777,6 +781,11 @@ public enum GroupFeature: String, Decodable, Feature { case .on: return "Allow to send files and media." case .off: return "Prohibit sending files and media." } + case .history: + switch enabled { + case .on: return "Send up to 100 last messages to new members." + case .off: return "Do not send history to new members." + } } } else { switch self { @@ -792,7 +801,7 @@ public enum GroupFeature: String, Decodable, Feature { } case .fullDelete: switch enabled { - case .on: return "Group members can irreversibly delete sent messages." + case .on: return "Group members can irreversibly delete sent messages. (24 hours)" case .off: return "Irreversible message deletion is prohibited in this group." } case .reactions: @@ -810,6 +819,11 @@ public enum GroupFeature: String, Decodable, Feature { case .on: return "Group members can send files and media." case .off: return "Files and media are prohibited in this group." } + case .history: + switch enabled { + case .on: return "Up to 100 last messages are sent to new members." + case .off: return "History is not sent to new members." + } } } } @@ -949,6 +963,7 @@ public struct FullGroupPreferences: Decodable, Equatable { public var reactions: GroupPreference public var voice: GroupPreference public var files: GroupPreference + public var history: GroupPreference public init( timedMessages: TimedMessagesGroupPreference, @@ -956,7 +971,8 @@ public struct FullGroupPreferences: Decodable, Equatable { fullDelete: GroupPreference, reactions: GroupPreference, voice: GroupPreference, - files: GroupPreference + files: GroupPreference, + history: GroupPreference ) { self.timedMessages = timedMessages self.directMessages = directMessages @@ -964,6 +980,7 @@ public struct FullGroupPreferences: Decodable, Equatable { self.reactions = reactions self.voice = voice self.files = files + self.history = history } public static let sampleData = FullGroupPreferences( @@ -972,7 +989,8 @@ public struct FullGroupPreferences: Decodable, Equatable { fullDelete: GroupPreference(enable: .off), reactions: GroupPreference(enable: .on), voice: GroupPreference(enable: .on), - files: GroupPreference(enable: .on) + files: GroupPreference(enable: .on), + history: GroupPreference(enable: .on) ) } @@ -983,14 +1001,16 @@ public struct GroupPreferences: Codable { public var reactions: GroupPreference? public var voice: GroupPreference? public var files: GroupPreference? + public var history: GroupPreference? public init( - timedMessages: TimedMessagesGroupPreference?, - directMessages: GroupPreference?, - fullDelete: GroupPreference?, - reactions: GroupPreference?, - voice: GroupPreference?, - files: GroupPreference? + timedMessages: TimedMessagesGroupPreference? = nil, + directMessages: GroupPreference? = nil, + fullDelete: GroupPreference? = nil, + reactions: GroupPreference? = nil, + voice: GroupPreference? = nil, + files: GroupPreference? = nil, + history: GroupPreference? = nil ) { self.timedMessages = timedMessages self.directMessages = directMessages @@ -998,6 +1018,7 @@ public struct GroupPreferences: Codable { self.reactions = reactions self.voice = voice self.files = files + self.history = history } public static let sampleData = GroupPreferences( @@ -1006,7 +1027,8 @@ public struct GroupPreferences: Codable { fullDelete: GroupPreference(enable: .off), reactions: GroupPreference(enable: .on), voice: GroupPreference(enable: .on), - files: GroupPreference(enable: .on) + files: GroupPreference(enable: .on), + history: GroupPreference(enable: .on) ) } @@ -1017,7 +1039,8 @@ public func toGroupPreferences(_ fullPreferences: FullGroupPreferences) -> Group fullDelete: fullPreferences.fullDelete, reactions: fullPreferences.reactions, voice: fullPreferences.voice, - files: fullPreferences.files + files: fullPreferences.files, + history: fullPreferences.history ) } @@ -1073,17 +1096,21 @@ public enum GroupFeatureEnabled: String, Codable, Identifiable { public enum ChatInfo: Identifiable, Decodable, NamedChat { case direct(contact: Contact) case group(groupInfo: GroupInfo) + case local(noteFolder: NoteFolder) case contactRequest(contactRequest: UserContactRequest) case contactConnection(contactConnection: PendingContactConnection) case invalidJSON(json: String) private static let invalidChatName = NSLocalizedString("invalid chat", comment: "invalid chat data") + static let privateNotesChatName = NSLocalizedString("Private notes", comment: "name of notes to self") + public var localDisplayName: String { get { switch self { case let .direct(contact): return contact.localDisplayName case let .group(groupInfo): return groupInfo.localDisplayName + case .local: return "" case let .contactRequest(contactRequest): return contactRequest.localDisplayName case let .contactConnection(contactConnection): return contactConnection.localDisplayName case .invalidJSON: return ChatInfo.invalidChatName @@ -1096,6 +1123,7 @@ public enum ChatInfo: Identifiable, Decodable, NamedChat { switch self { case let .direct(contact): return contact.displayName case let .group(groupInfo): return groupInfo.displayName + case .local: return ChatInfo.privateNotesChatName case let .contactRequest(contactRequest): return contactRequest.displayName case let .contactConnection(contactConnection): return contactConnection.displayName case .invalidJSON: return ChatInfo.invalidChatName @@ -1108,6 +1136,7 @@ public enum ChatInfo: Identifiable, Decodable, NamedChat { switch self { case let .direct(contact): return contact.fullName case let .group(groupInfo): return groupInfo.fullName + case .local: return "" case let .contactRequest(contactRequest): return contactRequest.fullName case let .contactConnection(contactConnection): return contactConnection.fullName case .invalidJSON: return ChatInfo.invalidChatName @@ -1120,6 +1149,7 @@ public enum ChatInfo: Identifiable, Decodable, NamedChat { switch self { case let .direct(contact): return contact.image case let .group(groupInfo): return groupInfo.image + case .local: return nil case let .contactRequest(contactRequest): return contactRequest.image case let .contactConnection(contactConnection): return contactConnection.image case .invalidJSON: return nil @@ -1132,6 +1162,7 @@ public enum ChatInfo: Identifiable, Decodable, NamedChat { switch self { case let .direct(contact): return contact.localAlias case let .group(groupInfo): return groupInfo.localAlias + case .local: return "" case let .contactRequest(contactRequest): return contactRequest.localAlias case let .contactConnection(contactConnection): return contactConnection.localAlias case .invalidJSON: return "" @@ -1144,6 +1175,7 @@ public enum ChatInfo: Identifiable, Decodable, NamedChat { switch self { case let .direct(contact): return contact.id case let .group(groupInfo): return groupInfo.id + case let .local(noteFolder): return noteFolder.id case let .contactRequest(contactRequest): return contactRequest.id case let .contactConnection(contactConnection): return contactConnection.id case .invalidJSON: return "" @@ -1156,6 +1188,7 @@ public enum ChatInfo: Identifiable, Decodable, NamedChat { switch self { case .direct: return .direct case .group: return .group + case .local: return .local case .contactRequest: return .contactRequest case .contactConnection: return .contactConnection case .invalidJSON: return .direct @@ -1168,6 +1201,7 @@ public enum ChatInfo: Identifiable, Decodable, NamedChat { switch self { case let .direct(contact): return contact.apiId case let .group(groupInfo): return groupInfo.apiId + case let .local(noteFolder): return noteFolder.apiId case let .contactRequest(contactRequest): return contactRequest.apiId case let .contactConnection(contactConnection): return contactConnection.apiId case .invalidJSON: return 0 @@ -1180,6 +1214,7 @@ public enum ChatInfo: Identifiable, Decodable, NamedChat { switch self { case let .direct(contact): return contact.ready case let .group(groupInfo): return groupInfo.ready + case let .local(noteFolder): return noteFolder.ready case let .contactRequest(contactRequest): return contactRequest.ready case let .contactConnection(contactConnection): return contactConnection.ready case .invalidJSON: return false @@ -1192,6 +1227,7 @@ public enum ChatInfo: Identifiable, Decodable, NamedChat { switch self { case let .direct(contact): return contact.sendMsgEnabled case let .group(groupInfo): return groupInfo.sendMsgEnabled + case let .local(noteFolder): return noteFolder.sendMsgEnabled case let .contactRequest(contactRequest): return contactRequest.sendMsgEnabled case let .contactConnection(contactConnection): return contactConnection.sendMsgEnabled case .invalidJSON: return false @@ -1204,6 +1240,7 @@ public enum ChatInfo: Identifiable, Decodable, NamedChat { switch self { case let .direct(contact): return contact.contactConnIncognito case let .group(groupInfo): return groupInfo.membership.memberIncognito + case .local: return false case .contactRequest: return false case let .contactConnection(contactConnection): return contactConnection.incognito case .invalidJSON: return false @@ -1246,6 +1283,11 @@ public enum ChatInfo: Identifiable, Decodable, NamedChat { case .voice: return prefs.voice.on case .calls: return false } + case .local: + switch feature { + case .voice: return true + default: return false + } default: return false } } @@ -1307,6 +1349,7 @@ public enum ChatInfo: Identifiable, Decodable, NamedChat { switch self { case let .direct(contact): return contact.createdAt case let .group(groupInfo): return groupInfo.createdAt + case let .local(noteFolder): return noteFolder.createdAt case let .contactRequest(contactRequest): return contactRequest.createdAt case let .contactConnection(contactConnection): return contactConnection.createdAt case .invalidJSON: return .now @@ -1317,6 +1360,7 @@ public enum ChatInfo: Identifiable, Decodable, NamedChat { switch self { case let .direct(contact): return contact.updatedAt case let .group(groupInfo): return groupInfo.updatedAt + case let .local(noteFolder): return noteFolder.updatedAt case let .contactRequest(contactRequest): return contactRequest.updatedAt case let .contactConnection(contactConnection): return contactConnection.updatedAt case .invalidJSON: return .now @@ -1326,6 +1370,7 @@ public enum ChatInfo: Identifiable, Decodable, NamedChat { public struct SampleData { public var direct: ChatInfo public var group: ChatInfo + public var local: ChatInfo public var contactRequest: ChatInfo public var contactConnection: ChatInfo } @@ -1333,6 +1378,7 @@ public enum ChatInfo: Identifiable, Decodable, NamedChat { public static var sampleData: ChatInfo.SampleData = SampleData( direct: ChatInfo.direct(contact: Contact.sampleData), group: ChatInfo.group(groupInfo: GroupInfo.sampleData), + local: ChatInfo.local(noteFolder: NoteFolder.sampleData), contactRequest: ChatInfo.contactRequest(contactRequest: UserContactRequest.sampleData), contactConnection: ChatInfo.contactConnection(contactConnection: PendingContactConnection.getSampleData()) ) @@ -1768,6 +1814,7 @@ public struct GroupMember: Identifiable, Decodable { public var memberCategory: GroupMemberCategory public var memberStatus: GroupMemberStatus public var memberSettings: GroupMemberSettings + public var blockedByAdmin: Bool public var invitedBy: InvitedBy public var localDisplayName: ContactName public var memberProfile: LocalProfile @@ -1779,13 +1826,15 @@ public struct GroupMember: Identifiable, Decodable { public var displayName: String { get { let p = memberProfile - return p.localAlias == "" ? p.displayName : p.localAlias + let name = p.localAlias == "" ? p.displayName : p.localAlias + return pastMember(name) } } public var fullName: String { get { memberProfile.fullName } } public var image: String? { get { memberProfile.image } } public var contactLink: String? { get { memberProfile.contactLink } } public var verified: Bool { activeConn?.connectionCode != nil } + public var blocked: Bool { blockedByAdmin || !memberSettings.showMessages } var directChatId: ChatId? { get { @@ -1800,17 +1849,27 @@ public struct GroupMember: Identifiable, Decodable { public var chatViewName: String { get { let p = memberProfile - return p.localAlias == "" - ? p.displayName + (p.fullName == "" || p.fullName == p.displayName ? "" : " / \(p.fullName)") - : p.localAlias + let name = ( + p.localAlias == "" + ? p.displayName + (p.fullName == "" || p.fullName == p.displayName ? "" : " / \(p.fullName)") + : p.localAlias + ) + return pastMember(name) } } + private func pastMember(_ name: String) -> String { + memberStatus == .memUnknown + ? String.localizedStringWithFormat(NSLocalizedString("Past member %@", comment: "past/unknown group member"), name) + : name + } + public var memberActive: Bool { switch memberStatus { case .memRemoved: return false case .memLeft: return false case .memGroupDeleted: return false + case .memUnknown: return false case .memInvited: return false case .memIntroduced: return false case .memIntroInvited: return false @@ -1827,6 +1886,7 @@ public struct GroupMember: Identifiable, Decodable { case .memRemoved: return false case .memLeft: return false case .memGroupDeleted: return false + case .memUnknown: return false case .memInvited: return false case .memIntroduced: return true case .memIntroInvited: return true @@ -1841,7 +1901,7 @@ public struct GroupMember: Identifiable, Decodable { public func canBeRemoved(groupInfo: GroupInfo) -> Bool { let userRole = groupInfo.membership.memberRole return memberStatus != .memRemoved && memberStatus != .memLeft - && userRole >= .admin && userRole >= memberRole && groupInfo.membership.memberCurrent + && userRole >= .admin && userRole >= memberRole && groupInfo.membership.memberActive } public func canChangeRoleTo(groupInfo: GroupInfo) -> [GroupMemberRole]? { @@ -1850,6 +1910,12 @@ public struct GroupMember: Identifiable, Decodable { return GroupMemberRole.allCases.filter { $0 <= userRole && $0 != .author } } + public func canBlockForAll(groupInfo: GroupInfo) -> Bool { + let userRole = groupInfo.membership.memberRole + return memberStatus != .memRemoved && memberStatus != .memLeft && memberRole < .admin + && userRole >= .admin && userRole >= memberRole && groupInfo.membership.memberActive + } + public var memberIncognito: Bool { memberProfile.profileId != memberContactProfileId } @@ -1862,6 +1928,7 @@ public struct GroupMember: Identifiable, Decodable { memberCategory: .inviteeMember, memberStatus: .memComplete, memberSettings: GroupMemberSettings(showMessages: true), + blockedByAdmin: false, invitedBy: .user, localDisplayName: "alice", memberProfile: LocalProfile.sampleData, @@ -1931,6 +1998,7 @@ public enum GroupMemberStatus: String, Decodable { case memRemoved = "removed" case memLeft = "left" case memGroupDeleted = "deleted" + case memUnknown = "unknown" case memInvited = "invited" case memIntroduced = "introduced" case memIntroInvited = "intro-inv" @@ -1945,6 +2013,7 @@ public enum GroupMemberStatus: String, Decodable { case .memRemoved: return "removed" case .memLeft: return "left" case .memGroupDeleted: return "group deleted" + case .memUnknown: return "unknown status" case .memInvited: return "invited" case .memIntroduced: return "connecting (introduced)" case .memIntroInvited: return "connecting (introduction invitation)" @@ -1961,6 +2030,7 @@ public enum GroupMemberStatus: String, Decodable { case .memRemoved: return "removed" case .memLeft: return "left" case .memGroupDeleted: return "group deleted" + case .memUnknown: return "unknown" case .memInvited: return "invited" case .memIntroduced: return "connecting" case .memIntroInvited: return "connecting" @@ -1973,6 +2043,37 @@ public enum GroupMemberStatus: String, Decodable { } } +public struct NoteFolder: Identifiable, Decodable, NamedChat { + public var noteFolderId: Int64 + public var favorite: Bool + public var unread: Bool + var createdAt: Date + public var updatedAt: Date + + public var id: ChatId { get { "*\(noteFolderId)" } } + public var apiId: Int64 { get { noteFolderId } } + public var ready: Bool { get { true } } + public var sendMsgEnabled: Bool { get { true } } + public var displayName: String { get { ChatInfo.privateNotesChatName } } + public var fullName: String { get { "" } } + public var image: String? { get { nil } } + public var localAlias: String { get { "" } } + + public var canEdit: Bool { true } + + public var canDelete: Bool { true } + + public var canAddMembers: Bool { false } + + public static let sampleData = NoteFolder( + noteFolderId: 1, + favorite: false, + unread: false, + createdAt: .now, + updatedAt: .now + ) +} + public enum InvitedBy: Decodable { case contact(byContactId: Int64) case user @@ -2092,6 +2193,7 @@ public struct ChatItem: Identifiable, Decodable { case .rcvDeleted: return true case .sndModerated: return true case .rcvModerated: return true + case .rcvBlocked: return true default: return false } } @@ -2136,50 +2238,53 @@ public struct ChatItem: Identifiable, Decodable { } } - private var showNtfDir: Bool { - return !chatDir.sent - } - public var showNotification: Bool { switch content { - case .sndMsgContent: return showNtfDir - case .rcvMsgContent: return showNtfDir - case .sndDeleted: return showNtfDir - case .rcvDeleted: return showNtfDir - case .sndCall: return showNtfDir + case .sndMsgContent: return false + case .rcvMsgContent: return meta.itemDeleted == nil + case .sndDeleted: return false + case .rcvDeleted: return false + case .sndCall: return false case .rcvCall: return false // notification is shown on .callInvitation instead - case .rcvIntegrityError: return showNtfDir - case .rcvDecryptionError: return showNtfDir - case .rcvGroupInvitation: return showNtfDir - case .sndGroupInvitation: return showNtfDir - case .rcvDirectEvent: return false + case .rcvIntegrityError: return false + case .rcvDecryptionError: return false + case .rcvGroupInvitation: return true + case .sndGroupInvitation: return false + case .rcvDirectEvent(rcvDirectEvent: let rcvDirectEvent): + switch rcvDirectEvent { + case .contactDeleted: return false + case .profileUpdated: return true + } case .rcvGroupEvent(rcvGroupEvent: let rcvGroupEvent): switch rcvGroupEvent { case .groupUpdated: return false case .memberConnected: return false case .memberRole: return false - case .userRole: return showNtfDir - case .userDeleted: return showNtfDir - case .groupDeleted: return showNtfDir + case .memberBlocked: return false + case .userRole: return true + case .userDeleted: return true + case .groupDeleted: return true case .memberAdded: return false case .memberLeft: return false case .memberDeleted: return false case .invitedViaGroupLink: return false case .memberCreatedContact: return false + case .memberProfileUpdated: return false } - case .sndGroupEvent: return showNtfDir + case .sndGroupEvent: return false case .rcvConnEvent: return false - case .sndConnEvent: return showNtfDir + case .sndConnEvent: return false case .rcvChatFeature: return false - case .sndChatFeature: return showNtfDir + case .sndChatFeature: return false case .rcvChatPreference: return false - case .sndChatPreference: return showNtfDir + case .sndChatPreference: return false case .rcvGroupFeature: return false - case .sndGroupFeature: return showNtfDir - case .rcvChatFeatureRejected: return showNtfDir - case .rcvGroupFeatureRejected: return showNtfDir - case .sndModerated: return true - case .rcvModerated: return true + case .sndGroupFeature: return false + case .rcvChatFeatureRejected: return true + case .rcvGroupFeatureRejected: return false + case .sndModerated: return false + case .rcvModerated: return false + case .rcvBlocked: return false case .invalidJSON: return false } } @@ -2205,18 +2310,25 @@ public struct ChatItem: Identifiable, Decodable { return fileSource.cryptoArgs != nil } - public var encryptLocalFile: Bool { - content.msgContent?.isVideo == false && - privacyEncryptLocalFilesGroupDefault.get() + public var memberDisplayName: String? { + if case let .groupRcv(groupMember) = chatDir { + switch content { + case let .rcvGroupEvent(rcvGroupEvent: .memberProfileUpdated(fromProfile, toProfile)): + toProfile.displayName != fromProfile.displayName || toProfile.fullName != fromProfile.fullName + ? nil + : groupMember.chatViewName + default: + groupMember.chatViewName + } + } else { + nil + } } - public var memberDisplayName: String? { - get { - if case let .groupRcv(groupMember) = chatDir { - return groupMember.chatViewName - } else { - return nil - } + public var localNote: Bool { + switch chatDir { + case .localSnd, .localRcv: return true + default: return false } } @@ -2381,6 +2493,8 @@ public enum CIDirection: Decodable { case directRcv case groupSnd case groupRcv(groupMember: GroupMember) + case localSnd + case localRcv public var sent: Bool { get { @@ -2389,6 +2503,8 @@ public enum CIDirection: Decodable { case .directRcv: return false case .groupSnd: return true case .groupRcv: return false + case .localSnd: return true + case .localRcv: return false } } } @@ -2555,12 +2671,14 @@ public enum SndCIStatusProgress: String, Decodable { public enum CIDeleted: Decodable { case deleted(deletedTs: Date?) case blocked(deletedTs: Date?) + case blockedByAdmin(deletedTs: Date?) case moderated(deletedTs: Date?, byGroupMember: GroupMember) var id: String { switch self { case .deleted: return "deleted" case .blocked: return "blocked" + case .blockedByAdmin: return "blocked by admin" case .moderated: return "moderated" } } @@ -2601,6 +2719,7 @@ public enum CIContent: Decodable, ItemContent { case rcvGroupFeatureRejected(groupFeature: GroupFeature) case sndModerated case rcvModerated + case rcvBlocked case invalidJSON(json: String) public var text: String { @@ -2631,6 +2750,7 @@ public enum CIContent: Decodable, ItemContent { case let .rcvGroupFeatureRejected(groupFeature): return String.localizedStringWithFormat("%@: received, prohibited", groupFeature.text) case .sndModerated: return NSLocalizedString("moderated", comment: "moderated chat item") case .rcvModerated: return NSLocalizedString("moderated", comment: "moderated chat item") + case .rcvBlocked: return NSLocalizedString("blocked by admin", comment: "blocked chat item") case .invalidJSON: return NSLocalizedString("invalid data", comment: "invalid chat item") } } @@ -2669,6 +2789,7 @@ public enum CIContent: Decodable, ItemContent { case .rcvDecryptionError: return true case .rcvGroupInvitation: return true case .rcvModerated: return true + case .rcvBlocked: return true case .invalidJSON: return true default: return false } @@ -2714,6 +2835,8 @@ public struct CIQuote: Decodable, ItemContent { case .directRcv: return nil case .groupSnd: return membership?.displayName ?? "you" case let .groupRcv(member): return member.displayName + case .localSnd: return "you" + case .localRcv: return nil case nil: return nil } } @@ -2873,6 +2996,39 @@ public struct CryptoFile: Codable { public static func plain(_ f: String) -> CryptoFile { CryptoFile(filePath: f, cryptoArgs: nil) } + + private func decryptToTmpFile(_ filesToDelete: inout Set<URL>) async -> URL? { + if let cfArgs = cryptoArgs { + let url = getAppFilePath(filePath) + let tempUrl = getTempFilesDirectory().appendingPathComponent(filePath) + _ = filesToDelete.insert(tempUrl) + do { + try decryptCryptoFile(fromPath: url.path, cryptoArgs: cfArgs, toPath: tempUrl.path) + return tempUrl + } catch { + logger.error("Error decrypting file: \(error.localizedDescription)") + } + } + return nil + } + + public func decryptedGet() -> URL? { + let decrypted = CryptoFile.decryptedUrls[filePath] + return if let decrypted = decrypted, FileManager.default.fileExists(atPath: decrypted.path) { decrypted } else { nil } + } + + public func decryptedGetOrCreate(_ filesToDelete: inout Set<URL>) async -> URL? { + if let decrypted = decryptedGet() { + return decrypted + } else if let decrypted = await decryptToTmpFile(&filesToDelete) { + CryptoFile.decryptedUrls[filePath] = decrypted + return decrypted + } else { + return nil + } + } + + static var decryptedUrls = Dictionary<String, URL>() } public struct CryptoFileArgs: Codable { @@ -2921,6 +3077,7 @@ private var rcvCancelAction = CancelAction( public enum FileProtocol: String, Decodable { case smp = "smp" case xftp = "xftp" + case local = "local" } public enum CIFileStatus: Decodable, Equatable { @@ -3108,6 +3265,10 @@ extension MsgContent: Encodable { public struct FormattedText: Decodable { public var text: String public var format: Format? + + public var isSecret: Bool { + if case .secret = format { true } else { false } + } } public enum Format: Decodable, Equatable { @@ -3121,6 +3282,15 @@ public enum Format: Decodable, Equatable { case simplexLink(linkType: SimplexLinkType, simplexUri: String, smpHosts: [String]) case email case phone + + public var isSimplexLink: Bool { + get { + switch (self) { + case .simplexLink: return true + default: return false + } + } + } } public enum SimplexLinkType: String, Decodable { @@ -3274,10 +3444,29 @@ public enum CIGroupInvitationStatus: String, Decodable { public enum RcvDirectEvent: Decodable { case contactDeleted + case profileUpdated(fromProfile: Profile, toProfile: Profile) var text: String { switch self { case .contactDeleted: return NSLocalizedString("deleted contact", comment: "rcv direct event chat item") + case let .profileUpdated(fromProfile, toProfile): return profileUpdatedText(fromProfile, toProfile) + } + } + + private func profileUpdatedText(_ from: Profile, _ to: Profile) -> String { + if to.displayName != from.displayName || to.fullName != from.fullName { + String.localizedStringWithFormat(NSLocalizedString("contact %@ changed to %@", comment: "profile update event chat item"), from.profileViewName, to.profileViewName) + } else if to.image != from.image { + to.image == nil + ? NSLocalizedString("removed profile picture", comment: "profile update event chat item") + : NSLocalizedString("set new profile picture", comment: "profile update event chat item") + } else if to.contactLink != from.contactLink { + to.contactLink == nil + ? NSLocalizedString("removed contact address", comment: "profile update event chat item") + : NSLocalizedString("set new contact address", comment: "profile update event chat item") + } else { + // shouldn't happen if backend correctly creates item; UI should be synchronized with backend + NSLocalizedString("updated profile", comment: "profile update event chat item") } } } @@ -3287,6 +3476,7 @@ public enum RcvGroupEvent: Decodable { case memberConnected case memberLeft case memberRole(groupMemberId: Int64, profile: Profile, role: GroupMemberRole) + case memberBlocked(groupMemberId: Int64, profile: Profile, blocked: Bool) case userRole(role: GroupMemberRole) case memberDeleted(groupMemberId: Int64, profile: Profile) case userDeleted @@ -3294,6 +3484,7 @@ public enum RcvGroupEvent: Decodable { case groupUpdated(groupProfile: GroupProfile) case invitedViaGroupLink case memberCreatedContact + case memberProfileUpdated(fromProfile: Profile, toProfile: Profile) var text: String { switch self { @@ -3303,6 +3494,12 @@ public enum RcvGroupEvent: Decodable { case .memberLeft: return NSLocalizedString("left", comment: "rcv group event chat item") case let .memberRole(_, profile, role): return String.localizedStringWithFormat(NSLocalizedString("changed role of %@ to %@", comment: "rcv group event chat item"), profile.profileViewName, role.text) + case let .memberBlocked(_, profile, blocked): + if blocked { + return String.localizedStringWithFormat(NSLocalizedString("blocked %@", comment: "rcv group event chat item"), profile.profileViewName) + } else { + return String.localizedStringWithFormat(NSLocalizedString("unblocked %@", comment: "rcv group event chat item"), profile.profileViewName) + } case let .userRole(role): return String.localizedStringWithFormat(NSLocalizedString("changed your role to %@", comment: "rcv group event chat item"), role.text) case let .memberDeleted(_, profile): @@ -3312,6 +3509,20 @@ public enum RcvGroupEvent: Decodable { case .groupUpdated: return NSLocalizedString("updated group profile", comment: "rcv group event chat item") case .invitedViaGroupLink: return NSLocalizedString("invited via your group link", comment: "rcv group event chat item") case .memberCreatedContact: return NSLocalizedString("connected directly", comment: "rcv group event chat item") + case let .memberProfileUpdated(fromProfile, toProfile): return profileUpdatedText(fromProfile, toProfile) + } + } + + private func profileUpdatedText(_ from: Profile, _ to: Profile) -> String { + if to.displayName != from.displayName || to.fullName != from.fullName { + String.localizedStringWithFormat(NSLocalizedString("member %@ changed to %@", comment: "profile update event chat item"), from.profileViewName, to.profileViewName) + } else if to.image != from.image { + to.image == nil + ? NSLocalizedString("removed profile picture", comment: "profile update event chat item") + : NSLocalizedString("set new profile picture", comment: "profile update event chat item") + } else { + // shouldn't happen if backend correctly creates item; UI should be synchronized with backend + NSLocalizedString("updated profile", comment: "profile update event chat item") } } } @@ -3319,6 +3530,7 @@ public enum RcvGroupEvent: Decodable { public enum SndGroupEvent: Decodable { case memberRole(groupMemberId: Int64, profile: Profile, role: GroupMemberRole) case userRole(role: GroupMemberRole) + case memberBlocked(groupMemberId: Int64, profile: Profile, blocked: Bool) case memberDeleted(groupMemberId: Int64, profile: Profile) case userLeft case groupUpdated(groupProfile: GroupProfile) @@ -3329,6 +3541,12 @@ public enum SndGroupEvent: Decodable { return String.localizedStringWithFormat(NSLocalizedString("you changed role of %@ to %@", comment: "snd group event chat item"), profile.profileViewName, role.text) case let .userRole(role): return String.localizedStringWithFormat(NSLocalizedString("you changed role for yourself to %@", comment: "snd group event chat item"), role.text) + case let .memberBlocked(_, profile, blocked): + if blocked { + return String.localizedStringWithFormat(NSLocalizedString("you blocked %@", comment: "snd group event chat item"), profile.profileViewName) + } else { + return String.localizedStringWithFormat(NSLocalizedString("you unblocked %@", comment: "snd group event chat item"), profile.profileViewName) + } case let .memberDeleted(_, profile): return String.localizedStringWithFormat(NSLocalizedString("you removed %@", comment: "snd group event chat item"), profile.profileViewName) case .userLeft: return NSLocalizedString("you left", comment: "snd group event chat item") diff --git a/apps/ios/SimpleXChat/FileUtils.swift b/apps/ios/SimpleXChat/FileUtils.swift index 60d281f146..7496bf7215 100644 --- a/apps/ios/SimpleXChat/FileUtils.swift +++ b/apps/ios/SimpleXChat/FileUtils.swift @@ -22,6 +22,8 @@ public let MAX_VIDEO_SIZE_AUTO_RCV: Int64 = 1_047_552 // 1023KB public let MAX_FILE_SIZE_XFTP: Int64 = 1_073_741_824 // 1GB +public let MAX_FILE_SIZE_LOCAL: Int64 = Int64.max + public let MAX_FILE_SIZE_SMP: Int64 = 8000000 public let MAX_VOICE_MESSAGE_LENGTH = TimeInterval(300) @@ -69,13 +71,29 @@ func fileModificationDate(_ path: String) -> Date? { } } +public func deleteAppDatabaseAndFiles() { + let fm = FileManager.default + let dbPath = getAppDatabasePath().path + do { + try fm.removeItem(atPath: dbPath + CHAT_DB) + try fm.removeItem(atPath: dbPath + AGENT_DB) + } catch let error { + logger.error("Failed to delete all databases: \(error)") + } + try? fm.removeItem(atPath: dbPath + CHAT_DB_BAK) + try? fm.removeItem(atPath: dbPath + AGENT_DB_BAK) + try? fm.removeItem(at: getTempFilesDirectory()) + try? fm.createDirectory(at: getTempFilesDirectory(), withIntermediateDirectories: true) + deleteAppFiles() + _ = kcDatabasePassword.remove() + storeDBPassphraseGroupDefault.set(true) +} + public func deleteAppFiles() { let fm = FileManager.default do { - let fileNames = try fm.contentsOfDirectory(atPath: getAppFilesDirectory().path) - for fileName in fileNames { - removeFile(fileName) - } + try fm.removeItem(at: getAppFilesDirectory()) + try fm.createDirectory(at: getAppFilesDirectory(), withIntermediateDirectories: true) } catch { logger.error("FileUtils deleteAppFiles error: \(error.localizedDescription)") } @@ -224,6 +242,7 @@ public func getMaxFileSize(_ fileProtocol: FileProtocol) -> Int64 { switch fileProtocol { case .xftp: return MAX_FILE_SIZE_XFTP case .smp: return MAX_FILE_SIZE_SMP + case .local: return MAX_FILE_SIZE_LOCAL } } diff --git a/apps/ios/bg.lproj/Localizable.strings b/apps/ios/bg.lproj/Localizable.strings index 5a704457d1..4d0ee65e46 100644 --- a/apps/ios/bg.lproj/Localizable.strings +++ b/apps/ios/bg.lproj/Localizable.strings @@ -20,11 +20,14 @@ "_italic_" = "\\_курсив_"; /* No comment provided by engineer. */ -"- connect to [directory service](simplex:/contact#/?v=1-4&smp=smp%3A%2F%2Fu2dS9sG8nMNURyZwqASV4yROM28Er0luVTx5X1CsMrU%3D%40smp4.simplex.im%2FeXSPwqTkKyDO3px4fLf1wx3MvPdjdLW3%23%2F%3Fv%3D1-2%26dh%3DMCowBQYDK2VuAyEAaiv6MkMH44L2TcYrt_CsX3ZvM11WgbMEUn0hkIKTOho%253D%26srv%3Do5vmywmrnaxalvz6wi3zicyftgio6psuvyniis6gco6bp6ekl4cqj4id.onion) (BETA)!\n- delivery receipts (up to 20 members).\n- faster and more stable." = "- свържете се с [директория за услуги](simplex:/contact#/?v=1-4&smp=smp%3A%2F%2Fu2dS9sG8nMNURyZwqASV4yROM28Er0luVTx5X1CsMrU%3D%40smp4.simplex.im%2FeXSPwqTkKyDO3px4fLf1wx3MvPdjd LW3%23%2F%3Fv%3D1-2%26dh %3DMCowBQYDK2VuAyEAaiv6MkMH44L2TcYrt_CsX3ZvM11WgbMEUn0hkIKTOho%253D%26srv%3Do5vmywmrnaxalvz6wi3zicyftgio6psuvyniis6gco6bp6ekl4cqj4id.onion) (БЕТА)!\n- потвърждениe за доставка (до 20 члена).\n- по-бързо и по-стабилно."; +"- connect to [directory service](simplex:/contact#/?v=1-4&smp=smp%3A%2F%2Fu2dS9sG8nMNURyZwqASV4yROM28Er0luVTx5X1CsMrU%3D%40smp4.simplex.im%2FeXSPwqTkKyDO3px4fLf1wx3MvPdjdLW3%23%2F%3Fv%3D1-2%26dh%3DMCowBQYDK2VuAyEAaiv6MkMH44L2TcYrt_CsX3ZvM11WgbMEUn0hkIKTOho%253D%26srv%3Do5vmywmrnaxalvz6wi3zicyftgio6psuvyniis6gco6bp6ekl4cqj4id.onion) (BETA)!\n- delivery receipts (up to 20 members).\n- faster and more stable." = "- свържете се с [директория за услуги](simplex:/contact#/?v=1-4&smp=smp%3A%2F%2Fu2dS9sG8nMNURyZwqASV4yROM28Er0luVTx5X1CsMrU%3D%40smp4.simplex.im%2FeXSPwqTkKyDO3px4fLf1wx3MvPdjdLW3%23%2F%3Fv%3D1-2%26dh%3DMCowBQYDK2VuAyEAaiv6MkMH44L2TcYrt_CsX3ZvM11WgbMEUn0hkIKTOho%253D%26srv%3Do5vmywmrnaxalvz6wi3zicyftgio6psuvyniis6gco6bp6ekl4cqj4id.onion) (БЕТА)!\n- потвърждениe за доставка (до 20 члена).\n- по-бързо и по-стабилно."; /* No comment provided by engineer. */ "- more stable message delivery.\n- a bit better groups.\n- and more!" = "- по-стабилна доставка на съобщения.\n- малко по-добри групи.\n- и още!"; +/* No comment provided by engineer. */ +"- optionally notify deleted contacts.\n- profile names with spaces.\n- and more!" = "- по желание уведомете изтритите контакти.\n- имена на профили с интервали.\n- и още!"; + /* No comment provided by engineer. */ "- voice messages up to 5 minutes.\n- custom time to disappear.\n- editing history." = "- гласови съобщения до 5 минути.\n- персонализирано време за изчезване.\n- история на редактиране."; @@ -43,6 +46,12 @@ /* No comment provided by engineer. */ "(" = "("; +/* No comment provided by engineer. */ +"(new)" = "(ново)"; + +/* No comment provided by engineer. */ +"(this device v%@)" = "(това устройство v%@)"; + /* No comment provided by engineer. */ ")" = ")"; @@ -55,11 +64,14 @@ /* No comment provided by engineer. */ "[Star on GitHub](https://github.com/simplex-chat/simplex-chat)" = "[Звезда в GitHub](https://github.com/simplex-chat/simplex-chat)"; +/* No comment provided by engineer. */ +"**Add contact**: to create a new invitation link, or connect via a link you received." = "**Добави контакт**: за създаване на нов линк или свързване чрез получен линк за връзка."; + /* No comment provided by engineer. */ "**Add new contact**: to create your one-time QR Code for your contact." = "**Добави нов контакт**: за да създадете своя еднократен QR код или линк за вашия контакт."; /* No comment provided by engineer. */ -"**Create link / QR code** for your contact to use." = "**Създай линк / QR код**, който вашият контакт да използва."; +"**Create group**: to create a new group." = "**Създай група**: за създаване на нова група."; /* No comment provided by engineer. */ "**e2e encrypted** audio call" = "**e2e криптиран**аудио разговор"; @@ -73,18 +85,12 @@ /* No comment provided by engineer. */ "**Most private**: do not use SimpleX Chat notifications server, check messages periodically in the background (depends on how often you use the app)." = "**Най-поверително**: не използвайте сървъра за известия SimpleX Chat, периодично проверявайте съобщенията във фонов режим (зависи от това колко често използвате приложението)."; -/* No comment provided by engineer. */ -"**Paste received link** or open it in the browser and tap **Open in mobile app**." = "**Поставете получения линк** или го отворете в браузъра и докоснете **Отваряне в мобилно приложение**."; - /* No comment provided by engineer. */ "**Please note**: you will NOT be able to recover or change passphrase if you lose it." = "**Моля, обърнете внимание**: НЯМА да можете да възстановите или промените паролата, ако я загубите."; /* No comment provided by engineer. */ "**Recommended**: device token and notifications are sent to SimpleX Chat notification server, but not the message content, size or who it is from." = "**Препоръчително**: токенът на устройството и известията се изпращат до сървъра за уведомяване на SimpleX Chat, но не и съдържанието, размерът на съобщението или от кого е."; -/* No comment provided by engineer. */ -"**Scan QR code**: to connect to your contact in person or via video call." = "**Сканирай QR код**: за да се свържете с вашия контакт лично или чрез видеообаждане."; - /* No comment provided by engineer. */ "**Warning**: Instant push notifications require passphrase saved in Keychain." = "**Внимание**: Незабавните push известия изискват парола, запазена в Keychain."; @@ -118,12 +124,18 @@ /* No comment provided by engineer. */ "%@ %@" = "%@ %@"; +/* No comment provided by engineer. */ +"%@ and %@" = "%@ и %@"; + /* No comment provided by engineer. */ "%@ and %@ connected" = "%@ и %@ са свързани"; /* copied message info, <sender> at <time> */ "%@ at %@:" = "%1$@ в %2$@:"; +/* No comment provided by engineer. */ +"%@ connected" = "%@ свързан"; + /* notification title */ "%@ is connected!" = "%@ е свързан!"; @@ -139,6 +151,9 @@ /* notification title */ "%@ wants to connect!" = "%@ иска да се свърже!"; +/* No comment provided by engineer. */ +"%@, %@ and %lld members" = "%@, %@ и %lld членове"; + /* No comment provided by engineer. */ "%@, %@ and %lld other members connected" = "%@, %@ и %lld други членове са свързани"; @@ -178,9 +193,21 @@ /* No comment provided by engineer. */ "%lld file(s) with total size of %@" = "%lld файл(а) с общ размер от %@"; +/* No comment provided by engineer. */ +"%lld group events" = "%lld групови събития"; + /* No comment provided by engineer. */ "%lld members" = "%lld членове"; +/* No comment provided by engineer. */ +"%lld messages blocked" = "%lld блокирани съобщения"; + +/* No comment provided by engineer. */ +"%lld messages marked deleted" = "%lld съобщения, маркирани като изтрити"; + +/* No comment provided by engineer. */ +"%lld messages moderated by %@" = "%lld съобщения, модерирани от %@"; + /* No comment provided by engineer. */ "%lld minutes" = "%lld минути"; @@ -229,6 +256,9 @@ /* No comment provided by engineer. */ "~strike~" = "\\~зачеркнат~"; +/* time to disappear */ +"0 sec" = "0 сек"; + /* No comment provided by engineer. */ "0s" = "0s"; @@ -247,9 +277,6 @@ /* time interval */ "1 week" = "1 седмица"; -/* No comment provided by engineer. */ -"1-time link" = "Еднократен линк"; - /* No comment provided by engineer. */ "5 minutes" = "5 минути"; @@ -317,6 +344,9 @@ /* No comment provided by engineer. */ "Add address to your profile, so that your contacts can share it with other people. Profile update will be sent to your contacts." = "Добавете адрес към вашия профил, така че вашите контакти да могат да го споделят с други хора. Актуализацията на профила ще бъде изпратена до вашите контакти."; +/* No comment provided by engineer. */ +"Add contact" = "Добави контакт"; + /* No comment provided by engineer. */ "Add preset servers" = "Добави предварително зададени сървъри"; @@ -371,6 +401,9 @@ /* No comment provided by engineer. */ "All messages will be deleted - this cannot be undone! The messages will be deleted ONLY for you." = "Всички съобщения ще бъдат изтрити - това не може да бъде отменено! Съобщенията ще бъдат изтрити САМО за вас."; +/* No comment provided by engineer. */ +"All new messages from %@ will be hidden!" = "Всички нови съобщения от %@ ще бъдат скрити!"; + /* No comment provided by engineer. */ "All your contacts will remain connected." = "Всички ваши контакти ще останат свързани."; @@ -387,7 +420,7 @@ "Allow disappearing messages only if your contact allows it to you." = "Позволи изчезващи съобщения само ако вашият контакт ги разрешава."; /* No comment provided by engineer. */ -"Allow irreversible message deletion only if your contact allows it to you." = "Позволи необратимо изтриване на съобщение само ако вашият контакт го рарешава."; +"Allow irreversible message deletion only if your contact allows it to you. (24 hours)" = "Позволи необратимо изтриване на съобщение само ако вашият контакт го рарешава. (24 часа)"; /* No comment provided by engineer. */ "Allow message reactions only if your contact allows them." = "Позволи реакции на съобщения само ако вашият контакт ги разрешава."; @@ -402,7 +435,7 @@ "Allow sending disappearing messages." = "Разреши изпращането на изчезващи съобщения."; /* No comment provided by engineer. */ -"Allow to irreversibly delete sent messages." = "Позволи необратимо изтриване на изпратените съобщения."; +"Allow to irreversibly delete sent messages. (24 hours)" = "Позволи необратимо изтриване на изпратените съобщения. (24 часа)"; /* No comment provided by engineer. */ "Allow to send files and media." = "Позволи изпращане на файлове и медия."; @@ -423,7 +456,7 @@ "Allow your contacts to call you." = "Позволи на вашите контакти да ви се обаждат."; /* No comment provided by engineer. */ -"Allow your contacts to irreversibly delete sent messages." = "Позволи на вашите контакти да изтриват необратимо изпратените съобщения."; +"Allow your contacts to irreversibly delete sent messages. (24 hours)" = "Позволи на вашите контакти да изтриват необратимо изпратените съобщения. (24 часа)"; /* No comment provided by engineer. */ "Allow your contacts to send disappearing messages." = "Позволи на вашите контакти да изпращат изчезващи съобщения."; @@ -434,6 +467,12 @@ /* No comment provided by engineer. */ "Already connected?" = "Вече сте свързани?"; +/* No comment provided by engineer. */ +"Already connecting!" = "В процес на свързване!"; + +/* No comment provided by engineer. */ +"Already joining the group!" = "Вече се присъединихте към групата!"; + /* pref value */ "always" = "винаги"; @@ -443,6 +482,9 @@ /* No comment provided by engineer. */ "An empty chat profile with the provided name is created, and the app opens as usual." = "Създаен беше празен профил за чат с предоставеното име и приложението се отвари както обикновено."; +/* No comment provided by engineer. */ +"and %lld other events" = "и %lld други събития"; + /* No comment provided by engineer. */ "Answer call" = "Отговор на повикване"; @@ -500,6 +542,9 @@ /* No comment provided by engineer. */ "Authentication unavailable" = "Идентификацията е недостъпна"; +/* member role */ +"author" = "автор"; + /* No comment provided by engineer. */ "Auto-accept" = "Автоматично приемане"; @@ -512,6 +557,9 @@ /* No comment provided by engineer. */ "Back" = "Назад"; +/* No comment provided by engineer. */ +"Bad desktop address" = "Грешен адрес на настолното устройство"; + /* integrity error chat item */ "bad message hash" = "лош хеш на съобщението"; @@ -524,9 +572,27 @@ /* No comment provided by engineer. */ "Bad message ID" = "Лошо ID на съобщението"; +/* No comment provided by engineer. */ +"Better groups" = "По-добри групи"; + /* No comment provided by engineer. */ "Better messages" = "По-добри съобщения"; +/* No comment provided by engineer. */ +"Block" = "Блокирай"; + +/* No comment provided by engineer. */ +"Block group members" = "Блокиране на членове на групата"; + +/* No comment provided by engineer. */ +"Block member" = "Блокирай член"; + +/* No comment provided by engineer. */ +"Block member?" = "Блокирай члена?"; + +/* No comment provided by engineer. */ +"blocked" = "блокиран"; + /* No comment provided by engineer. */ "bold" = "удебелен"; @@ -534,7 +600,7 @@ "Both you and your contact can add message reactions." = "И вие, и вашият контакт можете да добавяте реакции към съобщението."; /* No comment provided by engineer. */ -"Both you and your contact can irreversibly delete sent messages." = "И вие, и вашият контакт можете да изтриете необратимо изпратените съобщения."; +"Both you and your contact can irreversibly delete sent messages. (24 hours)" = "И вие, и вашият контакт можете да изтриете необратимо изпратените съобщения. (24 часа)"; /* No comment provided by engineer. */ "Both you and your contact can make calls." = "И вие, и вашият контакт можете да осъществявате обаждания."; @@ -567,7 +633,7 @@ "Calls" = "Обаждания"; /* No comment provided by engineer. */ -"Can't delete user profile!" = "Потребителският профил не може да се изтрие!"; +"Camera not available" = "Камерата е неодстъпна"; /* No comment provided by engineer. */ "Can't invite contact!" = "Не може да покани контакта!"; @@ -654,6 +720,9 @@ /* No comment provided by engineer. */ "Chat is stopped" = "Чатът е спрян"; +/* No comment provided by engineer. */ +"Chat is stopped. If you already used this database on another device, you should transfer it back before starting chat." = "Чатът е спрян. Ако вече сте използвали тази база данни на друго устройство, трябва да я прехвърлите обратно, преди да стартирате чата отново."; + /* No comment provided by engineer. */ "Chat preferences" = "Чат настройки"; @@ -720,27 +789,51 @@ /* server test step */ "Connect" = "Свързване"; +/* No comment provided by engineer. */ +"Connect automatically" = "Автоматично свъзрване"; + /* No comment provided by engineer. */ "Connect incognito" = "Свързване инкогнито"; +/* No comment provided by engineer. */ +"Connect to desktop" = "Свързване с настолно устройство"; + /* No comment provided by engineer. */ "connect to SimpleX Chat developers." = "свържете се с разработчиците на SimpleX Chat."; /* No comment provided by engineer. */ -"Connect via link" = "Свърване чрез линк"; +"Connect to yourself?" = "Свърване със себе си?"; /* No comment provided by engineer. */ -"Connect via link / QR code" = "Свърване чрез линк/QR код"; +"Connect to yourself?\nThis is your own one-time link!" = "Свърване със себе си?\nТова е вашят еднократен линк за връзка!"; + +/* No comment provided by engineer. */ +"Connect to yourself?\nThis is your own SimpleX address!" = "Свърване със себе си?\nТова е вашият личен SimpleX адрес!"; + +/* No comment provided by engineer. */ +"Connect via contact address" = "Свързване чрез адрес за контакт"; + +/* No comment provided by engineer. */ +"Connect via link" = "Свърване чрез линк"; /* No comment provided by engineer. */ "Connect via one-time link" = "Свързване чрез еднократен линк за връзка"; +/* No comment provided by engineer. */ +"Connect with %@" = "Свързване с %@"; + /* No comment provided by engineer. */ "connected" = "свързан"; +/* No comment provided by engineer. */ +"Connected desktop" = "Свързано настолно устройство"; + /* rcv group event chat item */ "connected directly" = "свързан директно"; +/* No comment provided by engineer. */ +"Connected to desktop" = "Свързан с настолно устройство"; + /* No comment provided by engineer. */ "connecting" = "свързване"; @@ -765,6 +858,9 @@ /* No comment provided by engineer. */ "Connecting server… (error: %@)" = "Свързване със сървър…(грешка: %@)"; +/* No comment provided by engineer. */ +"Connecting to desktop" = "Свързване с настолно устройство"; + /* chat list item title */ "connecting…" = "свързване…"; @@ -783,6 +879,9 @@ /* No comment provided by engineer. */ "Connection request sent!" = "Заявката за връзка е изпратена!"; +/* No comment provided by engineer. */ +"Connection terminated" = "Връзката е прекратена"; + /* No comment provided by engineer. */ "Connection timeout" = "Времето на изчакване за установяване на връзката изтече"; @@ -831,15 +930,24 @@ /* No comment provided by engineer. */ "Core version: v%@" = "Версия на ядрото: v%@"; +/* No comment provided by engineer. */ +"Correct name to %@?" = "Поправи име на %@?"; + /* No comment provided by engineer. */ "Create" = "Създай"; +/* No comment provided by engineer. */ +"Create a group using a random profile." = "Създай група с автоматично генериран профилл."; + /* No comment provided by engineer. */ "Create an address to let people connect with you." = "Създайте адрес, за да позволите на хората да се свързват с вас."; /* server test step */ "Create file" = "Създай файл"; +/* No comment provided by engineer. */ +"Create group" = "Създай група"; + /* No comment provided by engineer. */ "Create group link" = "Създай групов линк"; @@ -850,7 +958,7 @@ "Create new profile in [desktop app](https://simplex.chat/downloads/). 💻" = "Създайте нов профил в [настолното приложение](https://simplex.chat/downloads/). 💻"; /* No comment provided by engineer. */ -"Create one-time invitation link" = "Създай линк за еднократна покана"; +"Create profile" = "Създай профил"; /* server test step */ "Create queue" = "Създай опашка"; @@ -867,6 +975,9 @@ /* No comment provided by engineer. */ "Created on %@" = "Създаден на %@"; +/* No comment provided by engineer. */ +"Creating link…" = "Линкът се създава…"; + /* No comment provided by engineer. */ "creator" = "създател"; @@ -966,6 +1077,9 @@ /* chat item action */ "Delete" = "Изтрий"; +/* No comment provided by engineer. */ +"Delete %lld messages?" = "Изтриване на %lld съобщения?"; + /* No comment provided by engineer. */ "Delete address" = "Изтрий адрес"; @@ -978,6 +1092,9 @@ /* No comment provided by engineer. */ "Delete all files" = "Изтрий всички файлове"; +/* No comment provided by engineer. */ +"Delete and notify contact" = "Изтрий и уведоми контакт"; + /* No comment provided by engineer. */ "Delete archive" = "Изтрий архив"; @@ -999,6 +1116,9 @@ /* No comment provided by engineer. */ "Delete Contact" = "Изтрий контакт"; +/* No comment provided by engineer. */ +"Delete contact?\nThis cannot be undone!" = "Изтрий контакт?\nТова не може да бъде отменено!"; + /* No comment provided by engineer. */ "Delete database" = "Изтрий базата данни"; @@ -1074,6 +1194,9 @@ /* copied message info */ "Deleted at: %@" = "Изтрито на: %@"; +/* rcv direct event chat item */ +"deleted contact" = "изтрит контакт"; + /* rcv group event chat item */ "deleted group" = "групата изтрита"; @@ -1089,6 +1212,15 @@ /* No comment provided by engineer. */ "Description" = "Описание"; +/* No comment provided by engineer. */ +"Desktop address" = "Адрес на настолно устройство"; + +/* No comment provided by engineer. */ +"Desktop app version %@ is not compatible with this app." = "Версията на настолното приложение %@ не е съвместима с това приложение."; + +/* No comment provided by engineer. */ +"Desktop devices" = "Настолни устройства"; + /* No comment provided by engineer. */ "Develop" = "Разработване"; @@ -1152,12 +1284,21 @@ /* server test step */ "Disconnect" = "Прекъсни връзката"; +/* No comment provided by engineer. */ +"Disconnect desktop?" = "Прекъсни връзката с настолното устройство?"; + /* No comment provided by engineer. */ "Discover and join groups" = "Открийте и се присъединете към групи"; +/* No comment provided by engineer. */ +"Discover via local network" = "Открий през локалната мрежа"; + /* No comment provided by engineer. */ "Do it later" = "Отложи"; +/* No comment provided by engineer. */ +"Do not send history to new members." = "Не изпращай история на нови членове."; + /* No comment provided by engineer. */ "Do NOT use SimpleX for emergency calls." = "НЕ използвайте SimpleX за спешни повиквания."; @@ -1177,7 +1318,7 @@ "Download file" = "Свали файл"; /* No comment provided by engineer. */ -"Duplicate display name!" = "Дублирано показвано име!"; +"Duplicate display name!" = "Дублирано име!"; /* integrity error chat item */ "duplicate message" = "дублирано съобщение"; @@ -1203,6 +1344,9 @@ /* No comment provided by engineer. */ "Enable automatic message deletion?" = "Активиране на автоматично изтриване на съобщения?"; +/* No comment provided by engineer. */ +"Enable camera access" = "Разреши достъпа до камерата"; + /* No comment provided by engineer. */ "Enable for all" = "Активиране за всички"; @@ -1257,6 +1401,9 @@ /* notification */ "Encrypted message or another event" = "Криптирано съобщение или друго събитие"; +/* notification */ +"Encrypted message: app is stopped" = "Криптирано съобщение: приложението е спряно"; + /* notification */ "Encrypted message: database error" = "Криптирано съобщение: грешка в базата данни"; @@ -1290,6 +1437,12 @@ /* chat item text */ "encryption re-negotiation allowed for %@" = "разрешено повторно договаряне на криптиране за %@"; +/* message decrypt error item */ +"Encryption re-negotiation error" = "Грешка при повторно договаряне на криптиране"; + +/* No comment provided by engineer. */ +"Encryption re-negotiation failed." = "Неуспешно повторно договаряне на криптирането."; + /* chat item text */ "encryption re-negotiation required" = "необходимо е повторно договаряне на криптиране"; @@ -1305,6 +1458,9 @@ /* No comment provided by engineer. */ "Enter correct passphrase." = "Въведи правилна парола."; +/* No comment provided by engineer. */ +"Enter group name…" = "Въведи име на групата…"; + /* No comment provided by engineer. */ "Enter Passcode" = "Въведете kодa за достъп"; @@ -1317,12 +1473,18 @@ /* No comment provided by engineer. */ "Enter server manually" = "Въведи сървъра ръчно"; +/* No comment provided by engineer. */ +"Enter this device name…" = "Въведи името на това устройство…"; + /* placeholder */ "Enter welcome message…" = "Въведи съобщение при посрещане…"; /* placeholder */ "Enter welcome message… (optional)" = "Въведи съобщение при посрещане…(незадължително)"; +/* No comment provided by engineer. */ +"Enter your name…" = "Въведи своето име…"; + /* No comment provided by engineer. */ "error" = "грешка"; @@ -1413,6 +1575,9 @@ /* No comment provided by engineer. */ "Error loading %@ servers" = "Грешка при зареждане на %@ сървъри"; +/* No comment provided by engineer. */ +"Error opening chat" = "Грешка при отваряне на чата"; + /* No comment provided by engineer. */ "Error receiving file" = "Грешка при получаване на файл"; @@ -1437,6 +1602,9 @@ /* No comment provided by engineer. */ "Error saving user password" = "Грешка при запазване на потребителска парола"; +/* No comment provided by engineer. */ +"Error scanning code: %@" = "Грешка при сканиране на кода: %@"; + /* No comment provided by engineer. */ "Error sending email" = "Грешка при изпращане на имейл"; @@ -1494,6 +1662,9 @@ /* No comment provided by engineer. */ "Exit without saving" = "Изход без запазване"; +/* chat item action */ +"Expand" = "Разшири"; + /* No comment provided by engineer. */ "Export database" = "Експортирай база данни"; @@ -1512,6 +1683,9 @@ /* No comment provided by engineer. */ "Fast and no wait until the sender is online!" = "Бързо и без чакане, докато подателят е онлайн!"; +/* No comment provided by engineer. */ +"Faster joining and more reliable messages." = "По-бързо присъединяване и по-надеждни съобщения."; + /* No comment provided by engineer. */ "Favorite" = "Любим"; @@ -1569,6 +1743,9 @@ /* No comment provided by engineer. */ "For console" = "За конзолата"; +/* No comment provided by engineer. */ +"Found desktop" = "Намерено настолно устройство"; + /* No comment provided by engineer. */ "French interface" = "Френски интерфейс"; @@ -1581,6 +1758,9 @@ /* No comment provided by engineer. */ "Full name:" = "Пълно име:"; +/* No comment provided by engineer. */ +"Fully decentralized – visible only to members." = "Напълно децентрализирана – видима е само за членовете."; + /* No comment provided by engineer. */ "Fully re-implemented - work in background!" = "Напълно преработено - работи във фонов режим!"; @@ -1593,11 +1773,17 @@ /* No comment provided by engineer. */ "Group" = "Група"; +/* No comment provided by engineer. */ +"Group already exists" = "Групата вече съществува"; + +/* No comment provided by engineer. */ +"Group already exists!" = "Групата вече съществува!"; + /* No comment provided by engineer. */ "group deleted" = "групата е изтрита"; /* No comment provided by engineer. */ -"Group display name" = "Показвано име на групата"; +"Group display name" = "Име на групата"; /* No comment provided by engineer. */ "Group full name (optional)" = "Пълно име на групата (незадължително)"; @@ -1624,7 +1810,7 @@ "Group members can add message reactions." = "Членовете на групата могат да добавят реакции към съобщенията."; /* No comment provided by engineer. */ -"Group members can irreversibly delete sent messages." = "Членовете на групата могат необратимо да изтриват изпратените съобщения."; +"Group members can irreversibly delete sent messages. (24 hours)" = "Членовете на групата могат необратимо да изтриват изпратените съобщения. (24 часа)"; /* No comment provided by engineer. */ "Group members can send direct messages." = "Членовете на групата могат да изпращат лични съобщения."; @@ -1692,6 +1878,9 @@ /* No comment provided by engineer. */ "History" = "История"; +/* No comment provided by engineer. */ +"History is not sent to new members." = "Историята не се изпраща на нови членове."; + /* time unit */ "hours" = "часове"; @@ -1716,9 +1905,6 @@ /* No comment provided by engineer. */ "If you can't meet in person, show QR code in a video call, or share the link." = "Ако не можете да се срещнете лично, покажете QR код във видеоразговора или споделете линка."; -/* No comment provided by engineer. */ -"If you cannot meet in person, you can **scan QR code in the video call**, or your contact can share an invitation link." = "Ако не можете да се срещнете на живо, можете да **сканирате QR код във видеообаждането** или вашият контакт може да сподели линк за покана."; - /* No comment provided by engineer. */ "If you enter this passcode when opening the app, all app data will be irreversibly removed!" = "Ако въведете този kод за достъп, когато отваряте приложението, всички данни от приложението ще бъдат необратимо изтрити!"; @@ -1764,6 +1950,9 @@ /* No comment provided by engineer. */ "Incognito" = "Инкогнито"; +/* No comment provided by engineer. */ +"Incognito groups" = "Инкогнито групи"; + /* No comment provided by engineer. */ "Incognito mode" = "Режим инкогнито"; @@ -1791,6 +1980,9 @@ /* No comment provided by engineer. */ "Incompatible database version" = "Несъвместима версия на базата данни"; +/* No comment provided by engineer. */ +"Incompatible version" = "Несъвместима версия"; + /* PIN entry */ "Incorrect passcode" = "Неправилен kод за достъп"; @@ -1830,6 +2022,21 @@ /* invalid chat item */ "invalid data" = "невалидни данни"; +/* No comment provided by engineer. */ +"Invalid display name!" = "Невалидно име!"; + +/* No comment provided by engineer. */ +"Invalid link" = "Невалиден линк"; + +/* No comment provided by engineer. */ +"Invalid name!" = "Невалидно име!"; + +/* No comment provided by engineer. */ +"Invalid QR code" = "Невалиден QR код"; + +/* No comment provided by engineer. */ +"Invalid response" = "Невалиден отговор"; + /* No comment provided by engineer. */ "Invalid server address!" = "Невалиден адрес на сървъра!"; @@ -1908,12 +2115,30 @@ /* No comment provided by engineer. */ "Join group" = "Влез в групата"; +/* No comment provided by engineer. */ +"Join group?" = "Влез в групата?"; + /* No comment provided by engineer. */ "Join incognito" = "Влез инкогнито"; +/* No comment provided by engineer. */ +"Join with current profile" = "Присъединяване с текущия профил"; + +/* No comment provided by engineer. */ +"Join your group?\nThis is your link for group %@!" = "Влез в твоята група?\nТова е вашят линк за група %@!"; + /* No comment provided by engineer. */ "Joining group" = "Присъединяване към групата"; +/* No comment provided by engineer. */ +"Keep" = "Запази"; + +/* No comment provided by engineer. */ +"Keep the app open to use it from desktop" = "Дръжте приложението отворено, за да го използвате от настолното устройство"; + +/* No comment provided by engineer. */ +"Keep unused invitation?" = "Запази неизползваната покана за връзка?"; + /* No comment provided by engineer. */ "Keep your connections" = "Запазете връзките си"; @@ -1950,6 +2175,15 @@ /* No comment provided by engineer. */ "Limitations" = "Ограничения"; +/* No comment provided by engineer. */ +"Link mobile and desktop apps! 🔗" = "Свържете мобилни и настолни приложения! 🔗"; + +/* No comment provided by engineer. */ +"Linked desktop options" = "Настройки на запомнени настолни устройства"; + +/* No comment provided by engineer. */ +"Linked desktops" = "Запомнени настолни устройства"; + /* No comment provided by engineer. */ "LIVE" = "НА ЖИВО"; @@ -1959,6 +2193,9 @@ /* No comment provided by engineer. */ "Live messages" = "Съобщения на живо"; +/* No comment provided by engineer. */ +"Local" = "Локално"; + /* No comment provided by engineer. */ "Local name" = "Локално име"; @@ -2055,6 +2292,9 @@ /* No comment provided by engineer. */ "Messages & files" = "Съобщения и файлове"; +/* No comment provided by engineer. */ +"Messages from %@ will be shown!" = "Съобщенията от %@ ще бъдат показани!"; + /* No comment provided by engineer. */ "Migrating database archive…" = "Архивът на базата данни се мигрира…"; @@ -2127,6 +2367,9 @@ /* No comment provided by engineer. */ "never" = "никога"; +/* No comment provided by engineer. */ +"New chat" = "Нов чат"; + /* notification */ "New contact request" = "Нова заявка за контакт"; @@ -2140,7 +2383,7 @@ "New desktop app!" = "Ново настолно приложение!"; /* No comment provided by engineer. */ -"New display name" = "Ново показвано име"; +"New display name" = "Ново име"; /* No comment provided by engineer. */ "New in %@" = "Ново в %@"; @@ -2202,6 +2445,9 @@ /* copied message info in history */ "no text" = "няма текст"; +/* No comment provided by engineer. */ +"Not compatible!" = "Несъвместим!"; + /* No comment provided by engineer. */ "Notifications" = "Известия"; @@ -2222,9 +2468,6 @@ /* No comment provided by engineer. */ "Off" = "Изключено"; -/* No comment provided by engineer. */ -"Off (Local)" = "Изключено (Локално)"; - /* feature offered item */ "offered %@" = "предлага %@"; @@ -2234,6 +2477,9 @@ /* No comment provided by engineer. */ "Ok" = "Ок"; +/* No comment provided by engineer. */ +"OK" = "ОК"; + /* No comment provided by engineer. */ "Old database" = "Стара база данни"; @@ -2271,7 +2517,7 @@ "Only you can add message reactions." = "Само вие можете да добавяте реакции на съобщенията."; /* No comment provided by engineer. */ -"Only you can irreversibly delete messages (your contact can mark them for deletion)." = "Само вие можете необратимо да изтриете съобщения (вашият контакт може да ги маркира за изтриване)."; +"Only you can irreversibly delete messages (your contact can mark them for deletion). (24 hours)" = "Само вие можете необратимо да изтриете съобщения (вашият контакт може да ги маркира за изтриване). (24 часа)"; /* No comment provided by engineer. */ "Only you can make calls." = "Само вие можете да извършвате разговори."; @@ -2286,7 +2532,7 @@ "Only your contact can add message reactions." = "Само вашият контакт може да добавя реакции на съобщенията."; /* No comment provided by engineer. */ -"Only your contact can irreversibly delete messages (you can mark them for deletion)." = "Само вашият контакт може необратимо да изтрие съобщения (можете да ги маркирате за изтриване)."; +"Only your contact can irreversibly delete messages (you can mark them for deletion). (24 hours)" = "Само вашият контакт може необратимо да изтрие съобщения (можете да ги маркирате за изтриване). (24 часа)"; /* No comment provided by engineer. */ "Only your contact can make calls." = "Само вашият контакт може да извършва разговори."; @@ -2306,6 +2552,9 @@ /* authentication reason */ "Open chat console" = "Отвори конзолата"; +/* No comment provided by engineer. */ +"Open group" = "Отвори група"; + /* No comment provided by engineer. */ "Open Settings" = "Отвори настройки"; @@ -2316,7 +2565,13 @@ "Open-source protocol and code – anybody can run the servers." = "Протокол и код с отворен код – всеки може да оперира собствени сървъри."; /* No comment provided by engineer. */ -"Opening database…" = "Отваряне на база данни…"; +"Opening app…" = "Приложението се отваря…"; + +/* No comment provided by engineer. */ +"Or scan QR code" = "Или сканирай QR код"; + +/* No comment provided by engineer. */ +"Or show this code" = "Или покажи този код"; /* member role */ "owner" = "собственик"; @@ -2340,16 +2595,13 @@ "Password to show" = "Парола за показване"; /* No comment provided by engineer. */ -"Paste" = "Постави"; +"Paste desktop address" = "Постави адрес на настолно устройство"; /* No comment provided by engineer. */ "Paste image" = "Постави изображение"; /* No comment provided by engineer. */ -"Paste received link" = "Постави получения линк"; - -/* placeholder */ -"Paste the link you received to connect with your contact." = "Поставете линка, който сте получили, за да се свържете с вашия контакт."; +"Paste the link you received" = "Постави получения линк"; /* No comment provided by engineer. */ "peer-to-peer" = "peer-to-peer"; @@ -2381,6 +2633,9 @@ /* No comment provided by engineer. */ "Please check yours and your contact preferences." = "Моля, проверете вашите настройки и тези вашия за контакт."; +/* No comment provided by engineer. */ +"Please contact developers.\nError: %@" = "Моля, свържете се с разработчиците.\nГрешка: %@"; + /* No comment provided by engineer. */ "Please contact group admin." = "Моля, свържете се с груповия администартор."; @@ -2438,6 +2693,12 @@ /* No comment provided by engineer. */ "Profile image" = "Профилно изображение"; +/* No comment provided by engineer. */ +"Profile name" = "Име на профила"; + +/* No comment provided by engineer. */ +"Profile name:" = "Име на профила:"; + /* No comment provided by engineer. */ "Profile password" = "Профилна парола"; @@ -2498,6 +2759,9 @@ /* No comment provided by engineer. */ "Read more in [User Guide](https://simplex.chat/docs/guide/app-settings.html#your-simplex-contact-address)." = "Прочетете повече в [Ръководство за потребителя](https://simplex.chat/docs/guide/app-settings.html#your-simplex-contact-address)."; +/* No comment provided by engineer. */ +"Read more in [User Guide](https://simplex.chat/docs/guide/chat-profiles.html#incognito-mode)." = "Прочетете повече в [Ръководство за потребителя](https://simplex.chat/docs/guide/chat-profiles.html#incognito-mode)."; + /* No comment provided by engineer. */ "Read more in [User Guide](https://simplex.chat/docs/guide/readme.html#connect-to-friends)." = "Прочетете повече в [Ръководство на потребителя](https://simplex.chat/docs/guide/readme.html#connect-to-friends)."; @@ -2603,6 +2867,12 @@ /* No comment provided by engineer. */ "Renegotiate encryption?" = "Предоговори криптирането?"; +/* No comment provided by engineer. */ +"Repeat connection request?" = "Изпрати отново заявката за свързване?"; + +/* No comment provided by engineer. */ +"Repeat join request?" = "Изпрати отново заявката за присъединяване?"; + /* chat item action */ "Reply" = "Отговори"; @@ -2636,6 +2906,9 @@ /* No comment provided by engineer. */ "Restore database error" = "Грешка при възстановяване на базата данни"; +/* No comment provided by engineer. */ +"Retry" = "Опитай отново"; + /* chat item action */ "Reveal" = "Покажи"; @@ -2714,6 +2987,9 @@ /* No comment provided by engineer. */ "Scan QR code" = "Сканирай QR код"; +/* No comment provided by engineer. */ +"Scan QR code from desktop" = "Сканирай QR код от настолното устройство"; + /* No comment provided by engineer. */ "Scan security code from your contact's app." = "Сканирайте кода за сигурност от приложението на вашия контакт."; @@ -2723,6 +2999,9 @@ /* No comment provided by engineer. */ "Search" = "Търсене"; +/* No comment provided by engineer. */ +"Search or paste SimpleX link" = "Търсене или поставяне на SimpleX линк"; + /* network option */ "sec" = "сек."; @@ -2801,6 +3080,9 @@ /* No comment provided by engineer. */ "Send them from gallery or custom keyboards." = "Изпрати от галерия или персонализирани клавиатури."; +/* No comment provided by engineer. */ +"Send up to 100 last messages to new members." = "Изпращане до последните 100 съобщения на нови членове."; + /* No comment provided by engineer. */ "Sender cancelled file transfer." = "Подателят отмени прехвърлянето на файла."; @@ -2858,6 +3140,9 @@ /* No comment provided by engineer. */ "Servers" = "Сървъри"; +/* No comment provided by engineer. */ +"Session code" = "Код на сесията"; + /* No comment provided by engineer. */ "Set 1 day" = "Задай 1 ден"; @@ -2901,7 +3186,7 @@ "Share link" = "Сподели линк"; /* No comment provided by engineer. */ -"Share one-time invitation link" = "Сподели линк за еднократна покана"; +"Share this 1-time invite link" = "Сподели този еднократен линк за връзка"; /* No comment provided by engineer. */ "Share with contacts" = "Сподели с контактите"; @@ -2979,10 +3264,10 @@ "Somebody" = "Някой"; /* No comment provided by engineer. */ -"Start a new chat" = "Започни нов чат"; +"Start chat" = "Започни чат"; /* No comment provided by engineer. */ -"Start chat" = "Започни чат"; +"Start chat?" = "Стартирай чата?"; /* No comment provided by engineer. */ "Start migration" = "Започни миграция"; @@ -3044,12 +3329,21 @@ /* No comment provided by engineer. */ "Tap to activate profile." = "Докосни за активиране на профил."; +/* No comment provided by engineer. */ +"Tap to Connect" = "Докосни за свързване"; + /* No comment provided by engineer. */ "Tap to join" = "Докосни за вход"; /* No comment provided by engineer. */ "Tap to join incognito" = "Докосни за инкогнито вход"; +/* No comment provided by engineer. */ +"Tap to paste link" = "Докосни за поставяне на линк за връзка"; + +/* No comment provided by engineer. */ +"Tap to scan" = "Докосни за сканиране"; + /* No comment provided by engineer. */ "Tap to start a new chat" = "Докосни за започване на нов чат"; @@ -3095,6 +3389,9 @@ /* No comment provided by engineer. */ "The attempt to change database passphrase was not completed." = "Опитът за промяна на паролата на базата данни не беше завършен."; +/* No comment provided by engineer. */ +"The code you scanned is not a SimpleX link QR code." = "QR кодът, който сканирахте, не е SimpleX линк за връзка."; + /* No comment provided by engineer. */ "The connection you accepted will be cancelled!" = "Връзката, която приехте, ще бъде отказана!"; @@ -3137,15 +3434,12 @@ /* No comment provided by engineer. */ "The servers for new connections of your current chat profile **%@**." = "Сървърите за нови връзки на текущия ви чат профил **%@**."; +/* No comment provided by engineer. */ +"The text you pasted is not a SimpleX link." = "Текстът, който поставихте, не е SimpleX линк за връзка."; + /* No comment provided by engineer. */ "Theme" = "Тема"; -/* No comment provided by engineer. */ -"There should be at least one user profile." = "Трябва да има поне един потребителски профил."; - -/* No comment provided by engineer. */ -"There should be at least one visible user profile." = "Трябва да има поне един видим потребителски профил."; - /* No comment provided by engineer. */ "These settings are for your current profile **%@**." = "Тези настройки са за текущия ви профил **%@**."; @@ -3164,12 +3458,24 @@ /* notification title */ "this contact" = "този контакт"; +/* No comment provided by engineer. */ +"This device name" = "Името на това устройство"; + +/* No comment provided by engineer. */ +"This display name is invalid. Please choose another name." = "Това име е невалидно. Моля, изберете друго име."; + /* No comment provided by engineer. */ "This group has over %lld members, delivery receipts are not sent." = "Тази група има над %lld членове, потвърждения за доставка не се изпращат."; /* No comment provided by engineer. */ "This group no longer exists." = "Тази група вече не съществува."; +/* No comment provided by engineer. */ +"This is your own one-time link!" = "Това е вашят еднократен линк за връзка!"; + +/* No comment provided by engineer. */ +"This is your own SimpleX address!" = "Това е вашият личен SimpleX адрес!"; + /* No comment provided by engineer. */ "This setting applies to messages in your current chat profile **%@**." = "Тази настройка се прилага за съобщения в текущия ви профил **%@**."; @@ -3179,6 +3485,9 @@ /* No comment provided by engineer. */ "To connect, your contact can scan QR code or use the link in the app." = "За да се свърже, вашият контакт може да сканира QR код или да използва линка в приложението."; +/* No comment provided by engineer. */ +"To hide unwanted messages." = "Скриване на нежелани съобщения."; + /* No comment provided by engineer. */ "To make a new connection" = "За да направите нова връзка"; @@ -3218,15 +3527,21 @@ /* No comment provided by engineer. */ "Turn off" = "Изключи"; -/* No comment provided by engineer. */ -"Turn off notifications?" = "Изключи известията?"; - /* No comment provided by engineer. */ "Turn on" = "Включи"; /* No comment provided by engineer. */ "Unable to record voice message" = "Не може да се запише гласово съобщение"; +/* No comment provided by engineer. */ +"Unblock" = "Отблокирай"; + +/* No comment provided by engineer. */ +"Unblock member" = "Отблокирай член"; + +/* No comment provided by engineer. */ +"Unblock member?" = "Отблокирай член?"; + /* item status description */ "Unexpected error: %@" = "Неочаквана грешка: %@"; @@ -3266,6 +3581,12 @@ /* No comment provided by engineer. */ "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." = "Освен ако вашият контакт не е изтрил връзката или този линк вече е бил използван, това може да е грешка - моля, докладвайте.\nЗа да се свържете, моля, помолете вашия контакт да създаде друг линк за връзка и проверете дали имате стабилна мрежова връзка."; +/* No comment provided by engineer. */ +"Unlink" = "Забрави"; + +/* No comment provided by engineer. */ +"Unlink desktop?" = "Забрави настолно устройство?"; + /* No comment provided by engineer. */ "Unlock" = "Отключи"; @@ -3278,6 +3599,9 @@ /* No comment provided by engineer. */ "Unread" = "Непрочетено"; +/* No comment provided by engineer. */ +"Up to 100 last messages are sent to new members." = "На новите членове се изпращат до последните 100 съобщения."; + /* No comment provided by engineer. */ "Update" = "Актуализация"; @@ -3320,12 +3644,18 @@ /* No comment provided by engineer. */ "Use for new connections" = "Използвай за нови връзки"; +/* No comment provided by engineer. */ +"Use from desktop" = "Използвай от настолно устройство"; + /* No comment provided by engineer. */ "Use iOS call interface" = "Използвай интерфейса за повикване на iOS"; /* No comment provided by engineer. */ "Use new incognito profile" = "Използвай нов инкогнито профил"; +/* No comment provided by engineer. */ +"Use only local notifications?" = "Използвай само локални известия?"; + /* No comment provided by engineer. */ "Use server" = "Използвай сървър"; @@ -3341,12 +3671,24 @@ /* No comment provided by engineer. */ "Using SimpleX Chat servers." = "Използват се сървърите на SimpleX Chat."; +/* No comment provided by engineer. */ +"v%@" = "v%@"; + /* No comment provided by engineer. */ "v%@ (%@)" = "v%@ (%@)"; +/* No comment provided by engineer. */ +"Verify code with desktop" = "Потвръди кода с настолното устройство"; + +/* No comment provided by engineer. */ +"Verify connection" = "Потвръди връзките"; + /* No comment provided by engineer. */ "Verify connection security" = "Потвръди сигурността на връзката"; +/* No comment provided by engineer. */ +"Verify connections" = "Потвръди връзките"; + /* No comment provided by engineer. */ "Verify security code" = "Потвръди кода за сигурност"; @@ -3365,6 +3707,9 @@ /* No comment provided by engineer. */ "via relay" = "чрез реле"; +/* No comment provided by engineer. */ +"Via secure quantum resistant protocol." = "Чрез сигурен квантово устойчив протокол."; + /* No comment provided by engineer. */ "Video call" = "Видео разговор"; @@ -3383,6 +3728,9 @@ /* No comment provided by engineer. */ "View security code" = "Виж кода за сигурност"; +/* chat feature */ +"Visible history" = "Видима история"; + /* No comment provided by engineer. */ "Voice message…" = "Гласово съобщение…"; @@ -3404,6 +3752,9 @@ /* No comment provided by engineer. */ "waiting for confirmation…" = "чака се за потвърждение…"; +/* No comment provided by engineer. */ +"Waiting for desktop..." = "Изчакване на настолно устройство…"; + /* No comment provided by engineer. */ "Waiting for file" = "Изчаква се получаването на файла"; @@ -3468,11 +3819,32 @@ "You allow" = "Вие позволявате"; /* No comment provided by engineer. */ -"You already have a chat profile with the same display name. Please choose another name." = "Вече имате чат профил със същото показвано име. Моля, изберете друго име."; +"You already have a chat profile with the same display name. Please choose another name." = "Вече имате чат профил със същото име. Моля, изберете друго име."; /* No comment provided by engineer. */ "You are already connected to %@." = "Вече сте вече свързани с %@."; +/* No comment provided by engineer. */ +"You are already connecting to %@." = "Вече се свързвате с %@."; + +/* No comment provided by engineer. */ +"You are already connecting via this one-time link!" = "Вече се свързвате чрез този еднократен линк за връзка!"; + +/* No comment provided by engineer. */ +"You are already in group %@." = "Вече сте в група %@."; + +/* No comment provided by engineer. */ +"You are already joining the group %@." = "Вече се присъединявате към групата %@."; + +/* No comment provided by engineer. */ +"You are already joining the group via this link!" = "Вие вече се присъединявате към групата чрез този линк!"; + +/* No comment provided by engineer. */ +"You are already joining the group via this link." = "Вие вече се присъединявате към групата чрез този линк."; + +/* No comment provided by engineer. */ +"You are already joining the group!\nRepeat join request?" = "Вече се присъединихте към групата!\nИзпрати отново заявката за присъединяване?"; + /* No comment provided by engineer. */ "You are connected to the server used to receive messages from this contact." = "Вие сте свързани към сървъра, използван за получаване на съобщения от този контакт."; @@ -3488,9 +3860,6 @@ /* No comment provided by engineer. */ "You can accept calls from lock screen, without device and app authentication." = "Можете да приемате обаждания от заключен екран, без идентификация на устройство и приложението."; -/* No comment provided by engineer. */ -"You can also connect by clicking the link. If it opens in the browser, click **Open in mobile app** button." = "Можете също да се свържете, като натиснете върху линка. Ако се отвори в браузъра, натиснете върху бутона **Отваряне в мобилно приложение**."; - /* No comment provided by engineer. */ "You can create it later" = "Можете да го създадете по-късно"; @@ -3503,6 +3872,9 @@ /* No comment provided by engineer. */ "You can hide or mute a user profile - swipe it to the right." = "Можете да скриете или заглушите известията за потребителски профил - плъзнете надясно."; +/* No comment provided by engineer. */ +"You can make it visible to your SimpleX contacts via Settings." = "Можете да го направите видим за вашите контакти в SimpleX чрез Настройки."; + /* notification body */ "You can now send messages to %@" = "Вече можете да изпращате съобщения до %@"; @@ -3527,6 +3899,9 @@ /* No comment provided by engineer. */ "You can use markdown to format messages:" = "Можете да използвате markdown за форматиране на съобщенията:"; +/* No comment provided by engineer. */ +"You can view invitation link again in connection details." = "Можете да видите отново линкът за покана в подробностите за връзката."; + /* No comment provided by engineer. */ "You can't send messages!" = "Не може да изпращате съобщения!"; @@ -3548,6 +3923,12 @@ /* No comment provided by engineer. */ "You could not be verified; please try again." = "Не можахте да бъдете потвърдени; Моля, опитайте отново."; +/* No comment provided by engineer. */ +"You have already requested connection via this address!" = "Вече сте заявили връзка през този адрес!"; + +/* No comment provided by engineer. */ +"You have already requested connection!\nRepeat connection request?" = "Вече сте направили заявката за връзка!\nИзпрати отново заявката за свързване?"; + /* No comment provided by engineer. */ "You have no chats" = "Нямате чатове"; @@ -3590,6 +3971,9 @@ /* No comment provided by engineer. */ "You will be connected to group when the group host's device is online, please wait or check later!" = "Ще бъдете свързани с групата, когато устройството на домакина на групата е онлайн, моля, изчакайте или проверете по-късно!"; +/* No comment provided by engineer. */ +"You will be connected when group link host's device is online, please wait or check later!" = "Ще бъдете свързани, когато устройството на хоста на груповата връзка е онлайн, моля, изчакайте или проверете по-късно!"; + /* No comment provided by engineer. */ "You will be connected when your connection request is accepted, please wait or check later!" = "Ще бъдете свързани, когато заявката ви за връзка бъде приета, моля, изчакайте или проверете по-късно!"; @@ -3599,6 +3983,9 @@ /* No comment provided by engineer. */ "You will be required to authenticate when you start or resume the app after 30 seconds in background." = "Ще трябва да се идентифицирате, когато стартирате или възобновите приложението след 30 секунди във фонов режим."; +/* No comment provided by engineer. */ +"You will connect to all group members." = "Ще се свържете с всички членове на групата."; + /* No comment provided by engineer. */ "You will still receive calls and notifications from muted profiles when they are active." = "Все още ще получавате обаждания и известия от заглушени профили, когато са активни."; @@ -3641,9 +4028,6 @@ /* No comment provided by engineer. */ "Your contacts can allow full message deletion." = "Вашите контакти могат да позволят пълното изтриване на съобщението."; -/* No comment provided by engineer. */ -"Your contacts in SimpleX will see it.\nYou can change it in Settings." = "Вашите контакти в SimpleX ще го видят.\nМожете да го промените в Настройки."; - /* No comment provided by engineer. */ "Your contacts will remain connected." = "Вашите контакти ще останат свързани."; @@ -3662,6 +4046,9 @@ /* No comment provided by engineer. */ "Your privacy" = "Вашата поверителност"; +/* No comment provided by engineer. */ +"Your profile" = "Вашият профил"; + /* No comment provided by engineer. */ "Your profile **%@** will be shared." = "Вашият профил **%@** ще бъде споделен."; diff --git a/apps/ios/bg.lproj/SimpleX--iOS--InfoPlist.strings b/apps/ios/bg.lproj/SimpleX--iOS--InfoPlist.strings index d85455d875..8b1f135a62 100644 --- a/apps/ios/bg.lproj/SimpleX--iOS--InfoPlist.strings +++ b/apps/ios/bg.lproj/SimpleX--iOS--InfoPlist.strings @@ -7,6 +7,9 @@ /* Privacy - Face ID Usage Description */ "NSFaceIDUsageDescription" = "SimpleX използва Face ID за локалнa идентификация"; +/* Privacy - Local Network Usage Description */ +"NSLocalNetworkUsageDescription" = "SimpleX използва достъп до локална мрежа, за да позволи използването на потребителския чат профил чрез настолно приложение в същата мрежа."; + /* Privacy - Microphone Usage Description */ "NSMicrophoneUsageDescription" = "SimpleX се нуждае от достъп до микрофона за аудио и видео разговори и за запис на гласови съобщения."; diff --git a/apps/ios/cs.lproj/Localizable.strings b/apps/ios/cs.lproj/Localizable.strings index 26469bea98..9d8bd1e4a9 100644 --- a/apps/ios/cs.lproj/Localizable.strings +++ b/apps/ios/cs.lproj/Localizable.strings @@ -20,7 +20,7 @@ "_italic_" = "\\_kurzíva_"; /* No comment provided by engineer. */ -"- connect to [directory service](simplex:/contact#/?v=1-4&smp=smp%3A%2F%2Fu2dS9sG8nMNURyZwqASV4yROM28Er0luVTx5X1CsMrU%3D%40smp4.simplex.im%2FeXSPwqTkKyDO3px4fLf1wx3MvPdjdLW3%23%2F%3Fv%3D1-2%26dh%3DMCowBQYDK2VuAyEAaiv6MkMH44L2TcYrt_CsX3ZvM11WgbMEUn0hkIKTOho%253D%26srv%3Do5vmywmrnaxalvz6wi3zicyftgio6psuvyniis6gco6bp6ekl4cqj4id.onion) (BETA)!\n- delivery receipts (up to 20 members).\n- faster and more stable." = "- připojit k [adresářová služba](simplex:/contact#/?v=1-4&smp=smp%3A%2F%2Fu2dS9sG8nMNURyZwqASV4yROM28Er0luVTx5X1CsMrU%3D%40smp4.simplex.im%2FeXSPwqTkKyDO3px4fLf1wx3MvPdjdLW3%23%2F%3Fv%3D1-2%26dh%3DMCowBQYDK2VuAyEAaiv6MkMH44L2TcYrt_CsX3ZvM11WgbMEUn0hkIKTOho%253D%26srv%3Do5vmywmrnaxalvz6wi3zicyftgio6psuvyniis6gco6bp6ekl4cqj4id.cibule) (BETA)!\n- doručenky (až 20 členů).\n- Rychlejší a stabilnější."; +"- connect to [directory service](simplex:/contact#/?v=1-4&smp=smp%3A%2F%2Fu2dS9sG8nMNURyZwqASV4yROM28Er0luVTx5X1CsMrU%3D%40smp4.simplex.im%2FeXSPwqTkKyDO3px4fLf1wx3MvPdjdLW3%23%2F%3Fv%3D1-2%26dh%3DMCowBQYDK2VuAyEAaiv6MkMH44L2TcYrt_CsX3ZvM11WgbMEUn0hkIKTOho%253D%26srv%3Do5vmywmrnaxalvz6wi3zicyftgio6psuvyniis6gco6bp6ekl4cqj4id.onion) (BETA)!\n- delivery receipts (up to 20 members).\n- faster and more stable." = "- připojit k [adresářová služba](simplex:/contact#/?v=1-4&smp=smp%3A%2F%2Fu2dS9sG8nMNURyZwqASV4yROM28Er0luVTx5X1CsMrU%3D%40smp4.simplex.im%2FeXSPwqTkKyDO3px4fLf1wx3MvPdjdLW3%23%2F%3Fv%3D1-2%26dh%3DMCowBQYDK2VuAyEAaiv6MkMH44L2TcYrt_CsX3ZvM11WgbMEUn0hkIKTOho%253D%26srv%3Do5vmywmrnaxalvz6wi3zicyftgio6psuvyniis6gco6bp6ekl4cqj4id.onion) (BETA)!\n- doručenky (až 20 členů).\n- Rychlejší a stabilnější."; /* No comment provided by engineer. */ "- more stable message delivery.\n- a bit better groups.\n- and more!" = "- více stabilní doručování zpráv.\n- o trochu lepší skupiny.\n- a více!"; @@ -58,9 +58,6 @@ /* No comment provided by engineer. */ "**Add new contact**: to create your one-time QR Code for your contact." = "**Přidat nový kontakt**: pro vytvoření jednorázového QR kódu nebo odkazu pro váš kontakt."; -/* No comment provided by engineer. */ -"**Create link / QR code** for your contact to use." = "**Vytvořte odkaz / QR kód** pro váš kontakt."; - /* No comment provided by engineer. */ "**e2e encrypted** audio call" = "**e2e šifrovaný** audio hovor"; @@ -73,18 +70,12 @@ /* No comment provided by engineer. */ "**Most private**: do not use SimpleX Chat notifications server, check messages periodically in the background (depends on how often you use the app)." = "**Nejsoukromější**: nepoužívejte server oznámení SimpleX Chat, pravidelně kontrolujte zprávy na pozadí (závisí na tom, jak často aplikaci používáte)."; -/* No comment provided by engineer. */ -"**Paste received link** or open it in the browser and tap **Open in mobile app**." = "**Vložte přijatý odkaz** nebo jej otevřete v prohlížeči a klepněte na **Otevřít v mobilní aplikaci**."; - /* No comment provided by engineer. */ "**Please note**: you will NOT be able to recover or change passphrase if you lose it." = "**Upozornění**: Pokud heslo ztratíte, NEBUDETE jej moci obnovit ani změnit."; /* No comment provided by engineer. */ "**Recommended**: device token and notifications are sent to SimpleX Chat notification server, but not the message content, size or who it is from." = "**Doporučeno**: Token zařízení a oznámení se odesílají na oznamovací server SimpleX Chat, ale nikoli obsah, velikost nebo od koho jsou zprávy."; -/* No comment provided by engineer. */ -"**Scan QR code**: to connect to your contact in person or via video call." = "** Naskenujte QR kód**: pro připojení ke kontaktu osobně nebo prostřednictvím videohovoru."; - /* No comment provided by engineer. */ "**Warning**: Instant push notifications require passphrase saved in Keychain." = "**Upozornění**: Okamžitě doručovaná oznámení vyžadují přístupové heslo uložené v Klíčence."; @@ -118,12 +109,18 @@ /* No comment provided by engineer. */ "%@ %@" = "%@ %@"; +/* No comment provided by engineer. */ +"%@ and %@" = "%@ a %@"; + /* No comment provided by engineer. */ "%@ and %@ connected" = "%@ a %@ připojen"; /* copied message info, <sender> at <time> */ "%@ at %@:" = "%1$@ na %2$@:"; +/* No comment provided by engineer. */ +"%@ connected" = "%@ připojen"; + /* notification title */ "%@ is connected!" = "%@ je připojen!"; @@ -247,9 +244,6 @@ /* time interval */ "1 week" = "1 týden"; -/* No comment provided by engineer. */ -"1-time link" = "Jednorázový odkaz"; - /* No comment provided by engineer. */ "5 minutes" = "5 minut"; @@ -387,7 +381,7 @@ "Allow disappearing messages only if your contact allows it to you." = "Povolte mizící zprávy, pouze pokud vám to váš kontakt dovolí."; /* No comment provided by engineer. */ -"Allow irreversible message deletion only if your contact allows it to you." = "Povolte nevratné smazání zprávy pouze v případě, že vám to váš kontakt dovolí."; +"Allow irreversible message deletion only if your contact allows it to you. (24 hours)" = "Povolte nevratné smazání zprávy pouze v případě, že vám to váš kontakt dovolí. (24 hodin)"; /* No comment provided by engineer. */ "Allow message reactions only if your contact allows them." = "Povolit reakce na zprávy, pokud je váš kontakt povolí."; @@ -402,7 +396,7 @@ "Allow sending disappearing messages." = "Povolit odesílání mizících zpráv."; /* No comment provided by engineer. */ -"Allow to irreversibly delete sent messages." = "Povolit nevratné smazání odeslaných zpráv."; +"Allow to irreversibly delete sent messages. (24 hours)" = "Povolit nevratné smazání odeslaných zpráv. (24 hodin)"; /* No comment provided by engineer. */ "Allow to send files and media." = "Povolit odesílání souborů a médii."; @@ -423,7 +417,7 @@ "Allow your contacts to call you." = "Povolte svým kontaktům vám volat."; /* No comment provided by engineer. */ -"Allow your contacts to irreversibly delete sent messages." = "Umožněte svým kontaktům nevratně odstranit odeslané zprávy."; +"Allow your contacts to irreversibly delete sent messages. (24 hours)" = "Umožněte svým kontaktům nevratně odstranit odeslané zprávy. (24 hodin)"; /* No comment provided by engineer. */ "Allow your contacts to send disappearing messages." = "Umožněte svým kontaktům odesílat mizící zprávy."; @@ -534,7 +528,7 @@ "Both you and your contact can add message reactions." = "Vy i váš kontakt můžete přidávat reakce na zprávy."; /* No comment provided by engineer. */ -"Both you and your contact can irreversibly delete sent messages." = "Vy i váš kontakt můžete nevratně mazat odeslané zprávy."; +"Both you and your contact can irreversibly delete sent messages. (24 hours)" = "Vy i váš kontakt můžete nevratně mazat odeslané zprávy. (24 hodin)"; /* No comment provided by engineer. */ "Both you and your contact can make calls." = "Volat můžete vy i váš kontakt."; @@ -566,9 +560,6 @@ /* No comment provided by engineer. */ "Calls" = "Hovory"; -/* No comment provided by engineer. */ -"Can't delete user profile!" = "Nemohu smazat uživatelský profil!"; - /* No comment provided by engineer. */ "Can't invite contact!" = "Nelze pozvat kontakt!"; @@ -729,9 +720,6 @@ /* No comment provided by engineer. */ "Connect via link" = "Připojte se prostřednictvím odkazu"; -/* No comment provided by engineer. */ -"Connect via link / QR code" = "Připojit se prostřednictvím odkazu / QR kódu"; - /* No comment provided by engineer. */ "Connect via one-time link" = "Připojit se jednorázovým odkazem"; @@ -849,9 +837,6 @@ /* No comment provided by engineer. */ "Create new profile in [desktop app](https://simplex.chat/downloads/). 💻" = "Vytvořit nový profil v [desktop app](https://simplex.chat/downloads/). 💻"; -/* No comment provided by engineer. */ -"Create one-time invitation link" = "Vytvořit jednorázovou pozvánku"; - /* server test step */ "Create queue" = "Vytvořit frontu"; @@ -1621,7 +1606,7 @@ "Group members can add message reactions." = "Členové skupin mohou přidávat reakce na zprávy."; /* No comment provided by engineer. */ -"Group members can irreversibly delete sent messages." = "Členové skupiny mohou nevratně mazat odeslané zprávy."; +"Group members can irreversibly delete sent messages. (24 hours)" = "Členové skupiny mohou nevratně mazat odeslané zprávy. (24 hodin)"; /* No comment provided by engineer. */ "Group members can send direct messages." = "Členové skupiny mohou posílat přímé zprávy."; @@ -1713,9 +1698,6 @@ /* No comment provided by engineer. */ "If you can't meet in person, show QR code in a video call, or share the link." = "Pokud se nemůžete setkat osobně, zobrazte QR kód ve videohovoru nebo sdílejte odkaz."; -/* No comment provided by engineer. */ -"If you cannot meet in person, you can **scan QR code in the video call**, or your contact can share an invitation link." = "Pokud se nemůžete setkat osobně, můžete **naskenovat QR kód během videohovoru**, nebo váš kontakt může sdílet odkaz na pozvánku."; - /* No comment provided by engineer. */ "If you enter this passcode when opening the app, all app data will be irreversibly removed!" = "Pokud tento přístupový kód zadáte při otevření aplikace, všechna data budou nenávratně smazána!"; @@ -1956,6 +1938,9 @@ /* No comment provided by engineer. */ "Live messages" = "Živé zprávy"; +/* No comment provided by engineer. */ +"Local" = "Místní"; + /* No comment provided by engineer. */ "Local name" = "Místní název"; @@ -2219,9 +2204,6 @@ /* No comment provided by engineer. */ "Off" = "Vypnout"; -/* No comment provided by engineer. */ -"Off (Local)" = "Vypnuto (místní)"; - /* feature offered item */ "offered %@" = "nabídl %@"; @@ -2268,7 +2250,7 @@ "Only you can add message reactions." = "Reakce na zprávy můžete přidávat pouze vy."; /* No comment provided by engineer. */ -"Only you can irreversibly delete messages (your contact can mark them for deletion)." = "Nevratně mazat zprávy můžete pouze vy (váš kontakt je může označit ke smazání)."; +"Only you can irreversibly delete messages (your contact can mark them for deletion). (24 hours)" = "Nevratně mazat zprávy můžete pouze vy (váš kontakt je může označit ke smazání). (24 hodin)"; /* No comment provided by engineer. */ "Only you can make calls." = "Volat můžete pouze vy."; @@ -2283,7 +2265,7 @@ "Only your contact can add message reactions." = "Reakce na zprávy může přidávat pouze váš kontakt."; /* No comment provided by engineer. */ -"Only your contact can irreversibly delete messages (you can mark them for deletion)." = "Nevratně mazat zprávy může pouze váš kontakt (vy je můžete označit ke smazání)."; +"Only your contact can irreversibly delete messages (you can mark them for deletion). (24 hours)" = "Nevratně mazat zprávy může pouze váš kontakt (vy je můžete označit ke smazání). (24 hodin)"; /* No comment provided by engineer. */ "Only your contact can make calls." = "Volat může pouze váš kontakt."; @@ -2312,9 +2294,6 @@ /* No comment provided by engineer. */ "Open-source protocol and code – anybody can run the servers." = "Protokol a kód s otevřeným zdrojovým kódem - servery může provozovat kdokoli."; -/* No comment provided by engineer. */ -"Opening database…" = "Otvírání databáze…"; - /* member role */ "owner" = "vlastník"; @@ -2336,18 +2315,9 @@ /* No comment provided by engineer. */ "Password to show" = "Heslo k zobrazení"; -/* No comment provided by engineer. */ -"Paste" = "Vložit"; - /* No comment provided by engineer. */ "Paste image" = "Vložit obrázek"; -/* No comment provided by engineer. */ -"Paste received link" = "Vložení přijatého odkazu"; - -/* placeholder */ -"Paste the link you received to connect with your contact." = "Vložte odkaz, který jste obdrželi, do pole níže a spojte se se svým kontaktem."; - /* No comment provided by engineer. */ "peer-to-peer" = "peer-to-peer"; @@ -2897,9 +2867,6 @@ /* No comment provided by engineer. */ "Share link" = "Sdílet odkaz"; -/* No comment provided by engineer. */ -"Share one-time invitation link" = "Jednorázový zvací odkaz"; - /* No comment provided by engineer. */ "Share with contacts" = "Sdílet s kontakty"; @@ -2975,9 +2942,6 @@ /* notification title */ "Somebody" = "Někdo"; -/* No comment provided by engineer. */ -"Start a new chat" = "Začít nový chat"; - /* No comment provided by engineer. */ "Start chat" = "Začít chat"; @@ -3137,12 +3101,6 @@ /* No comment provided by engineer. */ "Theme" = "Téma"; -/* No comment provided by engineer. */ -"There should be at least one user profile." = "Měl by tam být alespoň jeden uživatelský profil."; - -/* No comment provided by engineer. */ -"There should be at least one visible user profile." = "Měl by tam být alespoň jeden viditelný uživatelský profil."; - /* No comment provided by engineer. */ "These settings are for your current profile **%@**." = "Toto nastavení je pro váš aktuální profil **%@**."; @@ -3215,9 +3173,6 @@ /* No comment provided by engineer. */ "Turn off" = "Vypnout"; -/* No comment provided by engineer. */ -"Turn off notifications?" = "Vypnout upozornění?"; - /* No comment provided by engineer. */ "Turn on" = "Zapnout"; @@ -3485,9 +3440,6 @@ /* No comment provided by engineer. */ "You can accept calls from lock screen, without device and app authentication." = "Můžete přijímat hovory z obrazovky zámku, bez ověření zařízení a aplikace."; -/* No comment provided by engineer. */ -"You can also connect by clicking the link. If it opens in the browser, click **Open in mobile app** button." = "Můžete se také připojit kliknutím na odkaz. Pokud se otevře v prohlížeči, klikněte na tlačítko **Otevřít v mobilní aplikaci**."; - /* No comment provided by engineer. */ "You can create it later" = "Můžete vytvořit později"; @@ -3638,9 +3590,6 @@ /* No comment provided by engineer. */ "Your contacts can allow full message deletion." = "Vaše kontakty mohou povolit úplné mazání zpráv."; -/* No comment provided by engineer. */ -"Your contacts in SimpleX will see it.\nYou can change it in Settings." = "Vaše kontakty v SimpleX ji uvidí.\nMůžete ji změnit v Nastavení."; - /* No comment provided by engineer. */ "Your contacts will remain connected." = "Vaše kontakty zůstanou připojeny."; diff --git a/apps/ios/de.lproj/Localizable.strings b/apps/ios/de.lproj/Localizable.strings index febd4c06a5..3bc7690c8d 100644 --- a/apps/ios/de.lproj/Localizable.strings +++ b/apps/ios/de.lproj/Localizable.strings @@ -29,7 +29,7 @@ "- optionally notify deleted contacts.\n- profile names with spaces.\n- and more!" = "- Optionale Benachrichtigung von gelöschten Kontakten.\n- Profilnamen mit Leerzeichen.\n- Und mehr!"; /* No comment provided by engineer. */ -"- voice messages up to 5 minutes.\n- custom time to disappear.\n- editing history." = "- Bis zu 5 Minuten lange Sprachnachrichten.\n- Zeitdauer für verschwindende Nachrichten anpassen.\n- Nachrichten-Historie bearbeiten."; +"- voice messages up to 5 minutes.\n- custom time to disappear.\n- editing history." = "- Bis zu 5 Minuten lange Sprachnachrichten\n- Zeitdauer für verschwindende Nachrichten anpassen\n- Nachrichtenverlauf bearbeiten"; /* No comment provided by engineer. */ ", " = ", "; @@ -65,10 +65,13 @@ "[Star on GitHub](https://github.com/simplex-chat/simplex-chat)" = "[Stern auf GitHub vergeben](https://github.com/simplex-chat/simplex-chat)"; /* No comment provided by engineer. */ -"**Add new contact**: to create your one-time QR Code for your contact." = "**Fügen Sie einen neuen Kontakt hinzu**: Erzeugen Sie einen Einmal-QR-Code oder -Link für Ihren Kontakt."; +"**Add contact**: to create a new invitation link, or connect via a link you received." = "**Kontakt hinzufügen**: Um einen neuen Einladungslink zu erstellen oder eine Verbindung über einen Link herzustellen, den Sie erhalten haben."; /* No comment provided by engineer. */ -"**Create link / QR code** for your contact to use." = "**Generieren Sie einen Einladungs-Link / QR code** für Ihren Kontakt."; +"**Add new contact**: to create your one-time QR Code for your contact." = "**Neuen Kontakt hinzufügen**: Um einen Einmal-QR-Code oder -Link für Ihren Kontakt zu erzeugen."; + +/* No comment provided by engineer. */ +"**Create group**: to create a new group." = "**Gruppe erstellen**: Um eine neue Gruppe zu erstellen."; /* No comment provided by engineer. */ "**e2e encrypted** audio call" = "**E2E-verschlüsselter** Audioanruf"; @@ -82,18 +85,12 @@ /* No comment provided by engineer. */ "**Most private**: do not use SimpleX Chat notifications server, check messages periodically in the background (depends on how often you use the app)." = "**Beste Privatsphäre**: Es wird kein SimpleX-Chat-Benachrichtigungs-Server genutzt, Nachrichten werden in periodischen Abständen im Hintergrund geprüft (dies hängt davon ab, wie häufig Sie die App nutzen)."; -/* No comment provided by engineer. */ -"**Paste received link** or open it in the browser and tap **Open in mobile app**." = "**Fügen Sie den von Ihrem Kontakt erhaltenen Link ein** oder öffnen Sie ihn im Browser und tippen Sie auf **In mobiler App öffnen**."; - /* No comment provided by engineer. */ "**Please note**: you will NOT be able to recover or change passphrase if you lose it." = "**Bitte beachten Sie**: Das Passwort kann NICHT wiederhergestellt oder geändert werden, wenn Sie es vergessen haben oder verlieren."; /* No comment provided by engineer. */ "**Recommended**: device token and notifications are sent to SimpleX Chat notification server, but not the message content, size or who it is from." = "**Empfohlen**: Nur Ihr Geräte-Token und ihre Benachrichtigungen werden an den SimpleX-Chat-Benachrichtigungs-Server gesendet, aber weder der Nachrichteninhalt noch deren Größe oder von wem sie gesendet wurde."; -/* No comment provided by engineer. */ -"**Scan QR code**: to connect to your contact in person or via video call." = "**Scannen Sie den QR-Code**, um sich während einem persönlichen Treffen oder per Videoanruf mit Ihrem Kontakt zu verbinden."; - /* No comment provided by engineer. */ "**Warning**: Instant push notifications require passphrase saved in Keychain." = "**Warnung**: Sofortige Push-Benachrichtigungen erfordern die Eingabe eines Passworts, welches in Ihrem Schlüsselbund gespeichert ist."; @@ -104,7 +101,7 @@ "# %@" = "# %@"; /* copied message info */ -"## History" = "## Vergangenheit"; +"## History" = "## Nachrichtenverlauf"; /* copied message info */ "## In reply to" = "## Als Antwort auf"; @@ -205,6 +202,9 @@ /* No comment provided by engineer. */ "%lld messages blocked" = "%lld Nachrichten blockiert"; +/* No comment provided by engineer. */ +"%lld messages blocked by admin" = "%lld Nachrichten wurden vom Administrator blockiert"; + /* No comment provided by engineer. */ "%lld messages marked deleted" = "%lld Nachrichten als gelöscht markiert"; @@ -280,9 +280,6 @@ /* time interval */ "1 week" = "wöchentlich"; -/* No comment provided by engineer. */ -"1-time link" = "Einmal-Link"; - /* No comment provided by engineer. */ "5 minutes" = "5 Minuten"; @@ -311,10 +308,10 @@ "Abort" = "Abbrechen"; /* No comment provided by engineer. */ -"Abort changing address" = "Wechsel der Adresse abbrechen"; +"Abort changing address" = "Wechsel der Empfängeradresse abbrechen"; /* No comment provided by engineer. */ -"Abort changing address?" = "Wechsel der Adresse abbrechen?"; +"Abort changing address?" = "Wechsel der Empfängeradresse abbrechen?"; /* No comment provided by engineer. */ "About SimpleX" = "Über SimpleX"; @@ -348,7 +345,10 @@ "accepted call" = "Anruf angenommen"; /* No comment provided by engineer. */ -"Add address to your profile, so that your contacts can share it with other people. Profile update will be sent to your contacts." = "Fügen Sie die Adresse zu Ihrem Profil hinzu, damit Ihre Kontakte sie mit anderen Personen teilen können. Es wird eine Profilaktualisierung an Ihre Kontakte gesendet."; +"Add address to your profile, so that your contacts can share it with other people. Profile update will be sent to your contacts." = "Fügen Sie die Adresse Ihrem Profil hinzu, damit Ihre Kontakte sie mit anderen Personen teilen können. Es wird eine Profilaktualisierung an Ihre Kontakte gesendet."; + +/* No comment provided by engineer. */ +"Add contact" = "Kontakt hinzufügen"; /* No comment provided by engineer. */ "Add preset servers" = "Füge voreingestellte Server hinzu"; @@ -372,7 +372,7 @@ "Address" = "Adresse"; /* No comment provided by engineer. */ -"Address change will be aborted. Old receiving address will be used." = "Der Wechsel der Adresse wird abgebrochen. Die bisherige Adresse wird weiter verwendet."; +"Address change will be aborted. Old receiving address will be used." = "Der Wechsel der Empfängeradresse wird abgebrochen. Die bisherige Adresse wird weiter verwendet."; /* member role */ "admin" = "Admin"; @@ -401,11 +401,14 @@ /* No comment provided by engineer. */ "All group members will remain connected." = "Alle Gruppenmitglieder bleiben verbunden."; +/* No comment provided by engineer. */ +"All messages will be deleted - this cannot be undone!" = "Es werden alle Nachrichten gelöscht. Dieser Vorgang kann nicht rückgängig gemacht werden!"; + /* No comment provided by engineer. */ "All messages will be deleted - this cannot be undone! The messages will be deleted ONLY for you." = "Alle Nachrichten werden gelöscht - dies kann nicht rückgängig gemacht werden! Die Nachrichten werden NUR bei Ihnen gelöscht."; /* No comment provided by engineer. */ -"All new messages from %@ will be hidden!" = "Alle neuen Nachrichten von %@ werden verborgen!"; +"All new messages from %@ will be hidden!" = "Von %@ werden alle neuen Nachrichten ausgeblendet!"; /* No comment provided by engineer. */ "All your contacts will remain connected." = "Alle Ihre Kontakte bleiben verbunden."; @@ -420,10 +423,10 @@ "Allow calls only if your contact allows them." = "Erlauben Sie Anrufe nur dann, wenn es Ihr Kontakt ebenfalls erlaubt."; /* No comment provided by engineer. */ -"Allow disappearing messages only if your contact allows it to you." = "Erlauben Sie verschwindende Nachrichten nur dann, wenn es Ihnen Ihr Kontakt ebenfalls erlaubt."; +"Allow disappearing messages only if your contact allows it to you." = "Erlauben Sie verschwindende Nachrichten nur dann, wenn es Ihr Kontakt ebenfalls erlaubt."; /* No comment provided by engineer. */ -"Allow irreversible message deletion only if your contact allows it to you." = "Erlauben Sie das unwiederbringliche Löschen von Nachrichten nur dann, wenn es Ihnen Ihr Kontakt ebenfalls erlaubt."; +"Allow irreversible message deletion only if your contact allows it to you. (24 hours)" = "Erlauben Sie das unwiederbringliche Löschen von Nachrichten nur dann, wenn es Ihnen Ihr Kontakt ebenfalls erlaubt. (24 Stunden)"; /* No comment provided by engineer. */ "Allow message reactions only if your contact allows them." = "Erlauben Sie Reaktionen auf Nachrichten nur dann, wenn es Ihr Kontakt ebenfalls erlaubt."; @@ -438,7 +441,7 @@ "Allow sending disappearing messages." = "Das Senden von verschwindenden Nachrichten erlauben."; /* No comment provided by engineer. */ -"Allow to irreversibly delete sent messages." = "Unwiederbringliches löschen von gesendeten Nachrichten erlauben."; +"Allow to irreversibly delete sent messages. (24 hours)" = "Unwiederbringliches löschen von gesendeten Nachrichten erlauben. (24 Stunden)"; /* No comment provided by engineer. */ "Allow to send files and media." = "Das Senden von Dateien und Medien erlauben."; @@ -459,7 +462,7 @@ "Allow your contacts to call you." = "Erlaubt Ihren Kontakten Sie anzurufen."; /* No comment provided by engineer. */ -"Allow your contacts to irreversibly delete sent messages." = "Erlauben Sie Ihren Kontakten gesendete Nachrichten unwiederbringlich zu löschen."; +"Allow your contacts to irreversibly delete sent messages. (24 hours)" = "Erlauben Sie Ihren Kontakten gesendete Nachrichten unwiederbringlich zu löschen. (24 Stunden)"; /* No comment provided by engineer. */ "Allow your contacts to send disappearing messages." = "Erlauben Sie Ihren Kontakten das Senden von verschwindenden Nachrichten."; @@ -584,17 +587,32 @@ /* No comment provided by engineer. */ "Block" = "Blockieren"; +/* No comment provided by engineer. */ +"Block for all" = "Für Alle blockieren"; + /* No comment provided by engineer. */ "Block group members" = "Gruppenmitglieder blockieren"; /* No comment provided by engineer. */ "Block member" = "Mitglied blockieren"; +/* No comment provided by engineer. */ +"Block member for all?" = "Mitglied für Alle blockieren?"; + /* No comment provided by engineer. */ "Block member?" = "Mitglied blockieren?"; /* No comment provided by engineer. */ -"blocked" = "blockiert"; +"blocked" = "Blockiert"; + +/* rcv group event chat item */ +"blocked %@" = "%@ wurde blockiert"; + +/* blocked chat item */ +"blocked by admin" = "wurde vom Administrator blockiert"; + +/* No comment provided by engineer. */ +"Blocked by admin" = "wurde vom Administrator blockiert"; /* No comment provided by engineer. */ "bold" = "fett"; @@ -603,7 +621,7 @@ "Both you and your contact can add message reactions." = "Sowohl Sie, als auch Ihr Kontakt können Reaktionen auf Nachrichten geben."; /* No comment provided by engineer. */ -"Both you and your contact can irreversibly delete sent messages." = "Sowohl Ihr Kontakt, als auch Sie können gesendete Nachrichten unwiederbringlich löschen."; +"Both you and your contact can irreversibly delete sent messages. (24 hours)" = "Sowohl Ihr Kontakt, als auch Sie können gesendete Nachrichten unwiederbringlich löschen. (24 Stunden)"; /* No comment provided by engineer. */ "Both you and your contact can make calls." = "Sowohl Sie, als auch Ihr Kontakt können Anrufe tätigen."; @@ -636,7 +654,7 @@ "Calls" = "Anrufe"; /* No comment provided by engineer. */ -"Can't delete user profile!" = "Das Benutzerprofil kann nicht gelöscht werden!"; +"Camera not available" = "Kamera nicht verfügbar"; /* No comment provided by engineer. */ "Can't invite contact!" = "Kontakt kann nicht eingeladen werden!"; @@ -688,7 +706,7 @@ "Change self-destruct passcode" = "Selbstzerstörungs-Zugangscode ändern"; /* chat item text */ -"changed address for you" = "wechselte die Adresse für Sie"; +"changed address for you" = "Wechselte die Empfängeradresse von Ihnen"; /* rcv group event chat item */ "changed role of %@ to %@" = "änderte die Rolle von %1$@ auf %2$@"; @@ -697,10 +715,10 @@ "changed your role to %@" = "änderte Ihre Rolle auf %@"; /* chat item text */ -"changing address for %@…" = "Adresse von %@ wechseln…"; +"changing address for %@…" = "Empfängeradresse für %@ wechseln wird gestartet…"; /* chat item text */ -"changing address…" = "Wechsel der Adresse…"; +"changing address…" = "Wechsel der Empfängeradresse wurde gestartet…"; /* No comment provided by engineer. */ "Chat archive" = "Datenbank Archiv"; @@ -723,6 +741,9 @@ /* No comment provided by engineer. */ "Chat is stopped" = "Der Chat ist beendet"; +/* No comment provided by engineer. */ +"Chat is stopped. If you already used this database on another device, you should transfer it back before starting chat." = "Der Chat ist angehalten. Wenn Sie diese Datenbank bereits auf einem anderen Gerät genutzt haben, sollten Sie diese vor dem Starten des Chats wieder zurückspielen."; + /* No comment provided by engineer. */ "Chat preferences" = "Chat-Präferenzen"; @@ -750,6 +771,9 @@ /* No comment provided by engineer. */ "Clear conversation?" = "Unterhaltung löschen?"; +/* No comment provided by engineer. */ +"Clear private notes?" = "Private Notizen löschen?"; + /* No comment provided by engineer. */ "Clear verification" = "Überprüfung zurücknehmen"; @@ -808,7 +832,7 @@ "Connect to yourself?\nThis is your own one-time link!" = "Mit Ihnen selbst verbinden?\nDas ist Ihr eigener Einmal-Link!"; /* No comment provided by engineer. */ -"Connect to yourself?\nThis is your own SimpleX address!" = "Mit Ihnen selbst verbinden?\nDas ist Ihre eigene SimpleX-Adresse!"; +"Connect to yourself?\nThis is your own SimpleX address!" = "Sich mit Ihnen selbst verbinden?\nDas ist Ihre eigene SimpleX-Adresse!"; /* No comment provided by engineer. */ "Connect via contact address" = "Über die Kontakt-Adresse verbinden"; @@ -816,9 +840,6 @@ /* No comment provided by engineer. */ "Connect via link" = "Über einen Link verbinden"; -/* No comment provided by engineer. */ -"Connect via link / QR code" = "Über einen Link / QR-Code verbinden"; - /* No comment provided by engineer. */ "Connect via one-time link" = "Über einen Einmal-Link verbinden"; @@ -891,6 +912,9 @@ /* connection information */ "connection:%@" = "Verbindung:%@"; +/* profile update event chat item */ +"contact %@ changed to %@" = "Der Kontaktname %1$@ wurde auf %2$@ geändert"; + /* No comment provided by engineer. */ "Contact allows" = "Der Kontakt erlaubt"; @@ -960,9 +984,6 @@ /* No comment provided by engineer. */ "Create new profile in [desktop app](https://simplex.chat/downloads/). 💻" = "Neues Profil in der [Desktop-App] erstellen (https://simplex.chat/downloads/). 💻"; -/* No comment provided by engineer. */ -"Create one-time invitation link" = "Einmal-Einladungslink erstellen"; - /* No comment provided by engineer. */ "Create profile" = "Profil erstellen"; @@ -978,9 +999,18 @@ /* No comment provided by engineer. */ "Create your profile" = "Erstellen Sie Ihr Profil"; +/* No comment provided by engineer. */ +"Created at" = "Erstellt um"; + +/* copied message info */ +"Created at: %@" = "Erstellt um: %@"; + /* No comment provided by engineer. */ "Created on %@" = "Erstellt am %@"; +/* No comment provided by engineer. */ +"Creating link…" = "Link wird erstellt…"; + /* No comment provided by engineer. */ "creator" = "Ersteller"; @@ -1270,7 +1300,7 @@ "Disappearing message" = "Verschwindende Nachricht"; /* chat feature */ -"Disappearing messages" = "verschwindende Nachrichten"; +"Disappearing messages" = "Verschwindende Nachrichten"; /* No comment provided by engineer. */ "Disappearing messages are prohibited in this chat." = "In diesem Chat sind verschwindende Nachrichten nicht erlaubt."; @@ -1299,6 +1329,9 @@ /* No comment provided by engineer. */ "Do it later" = "Später wiederholen"; +/* No comment provided by engineer. */ +"Do not send history to new members." = "Den Nachrichtenverlauf nicht an neue Mitglieder senden."; + /* No comment provided by engineer. */ "Do NOT use SimpleX for emergency calls." = "Nutzen Sie SimpleX nicht für Notrufe."; @@ -1344,6 +1377,9 @@ /* No comment provided by engineer. */ "Enable automatic message deletion?" = "Automatisches Löschen von Nachrichten aktivieren?"; +/* No comment provided by engineer. */ +"Enable camera access" = "Kamera-Zugriff aktivieren"; + /* No comment provided by engineer. */ "Enable for all" = "Für Alle aktivieren"; @@ -1398,6 +1434,9 @@ /* notification */ "Encrypted message or another event" = "Verschlüsselte Nachricht oder ein anderes Ereignis"; +/* notification */ +"Encrypted message: app is stopped" = "Verschlüsselte Nachricht: Die App ist angehalten"; + /* notification */ "Encrypted message: database error" = "Verschlüsselte Nachricht: Datenbankfehler"; @@ -1498,7 +1537,7 @@ "Error adding member(s)" = "Fehler beim Hinzufügen von Mitgliedern"; /* No comment provided by engineer. */ -"Error changing address" = "Fehler beim Wechseln der Adresse"; +"Error changing address" = "Fehler beim Wechseln der Empfängeradresse"; /* No comment provided by engineer. */ "Error changing role" = "Fehler beim Ändern der Rolle"; @@ -1518,6 +1557,9 @@ /* No comment provided by engineer. */ "Error creating member contact" = "Fehler beim Anlegen eines Mitglied-Kontaktes"; +/* No comment provided by engineer. */ +"Error creating message" = "Fehler beim Erstellen der Nachricht"; + /* No comment provided by engineer. */ "Error creating profile!" = "Fehler beim Erstellen des Profils!"; @@ -1569,6 +1611,9 @@ /* No comment provided by engineer. */ "Error loading %@ servers" = "Fehler beim Laden von %@ Servern"; +/* No comment provided by engineer. */ +"Error opening chat" = "Fehler beim Öffnen des Chats"; + /* No comment provided by engineer. */ "Error receiving file" = "Fehler beim Empfangen der Datei"; @@ -1593,6 +1638,9 @@ /* No comment provided by engineer. */ "Error saving user password" = "Fehler beim Speichern des Benutzer-Passworts"; +/* No comment provided by engineer. */ +"Error scanning code: %@" = "Fehler beim Scannen des Codes: %@"; + /* No comment provided by engineer. */ "Error sending email" = "Fehler beim Senden der eMail"; @@ -1798,7 +1846,7 @@ "Group members can add message reactions." = "Gruppenmitglieder können eine Reaktion auf Nachrichten geben."; /* No comment provided by engineer. */ -"Group members can irreversibly delete sent messages." = "Gruppenmitglieder können gesendete Nachrichten unwiederbringlich löschen."; +"Group members can irreversibly delete sent messages. (24 hours)" = "Gruppenmitglieder können gesendete Nachrichten unwiederbringlich löschen. (24 Stunden)"; /* No comment provided by engineer. */ "Group members can send direct messages." = "Gruppenmitglieder können Direktnachrichten versenden."; @@ -1864,7 +1912,10 @@ "Hide:" = "Verberge:"; /* No comment provided by engineer. */ -"History" = "Vergangenheit"; +"History" = "Nachrichtenverlauf"; + +/* No comment provided by engineer. */ +"History is not sent to new members." = "Der Nachrichtenverlauf wird nicht an neue Gruppenmitglieder gesendet."; /* time unit */ "hours" = "Stunden"; @@ -1890,9 +1941,6 @@ /* No comment provided by engineer. */ "If you can't meet in person, show QR code in a video call, or share the link." = "Falls Sie sich nicht persönlich treffen können, zeigen Sie den QR-Code in einem Videoanruf oder teilen Sie den Link."; -/* No comment provided by engineer. */ -"If you cannot meet in person, you can **scan QR code in the video call**, or your contact can share an invitation link." = "Wenn Sie sich nicht persönlich treffen können, kann der **QR-Code während eines Videoanrufs gescannt werden**, oder Ihr Kontakt kann den Einladungslink über einen anderen Kanal mit Ihnen teilen."; - /* No comment provided by engineer. */ "If you enter this passcode when opening the app, all app data will be irreversibly removed!" = "Wenn Sie diesen Zugangscode während des Öffnens der App eingeben, werden alle App-Daten unwiederbringlich gelöscht!"; @@ -1926,6 +1974,9 @@ /* No comment provided by engineer. */ "Import database" = "Datenbank importieren"; +/* No comment provided by engineer. */ +"Improved message delivery" = "Verbesserte Zustellung von Nachrichten"; + /* No comment provided by engineer. */ "Improved privacy and security" = "Verbesserte Privatsphäre und Sicherheit"; @@ -2010,9 +2061,21 @@ /* invalid chat item */ "invalid data" = "Ungültige Daten"; +/* No comment provided by engineer. */ +"Invalid display name!" = "Ungültiger Anzeigename!"; + +/* No comment provided by engineer. */ +"Invalid link" = "Ungültiger Link"; + /* No comment provided by engineer. */ "Invalid name!" = "Ungültiger Name!"; +/* No comment provided by engineer. */ +"Invalid QR code" = "Ungültiger QR-Code"; + +/* No comment provided by engineer. */ +"Invalid response" = "Ungültige Reaktion"; + /* No comment provided by engineer. */ "Invalid server address!" = "Ungültige Serveradresse!"; @@ -2091,6 +2154,9 @@ /* No comment provided by engineer. */ "Join group" = "Treten Sie der Gruppe bei"; +/* No comment provided by engineer. */ +"Join group conversations" = "Gruppenunterhaltungen beitreten"; + /* No comment provided by engineer. */ "Join group?" = "Der Gruppe beitreten?"; @@ -2106,9 +2172,15 @@ /* No comment provided by engineer. */ "Joining group" = "Der Gruppe beitreten"; +/* No comment provided by engineer. */ +"Keep" = "Behalten"; + /* No comment provided by engineer. */ "Keep the app open to use it from desktop" = "Die App muss geöffnet bleiben, um sie vom Desktop aus nutzen zu können"; +/* No comment provided by engineer. */ +"Keep unused invitation?" = "Nicht genutzte Einladung behalten?"; + /* No comment provided by engineer. */ "Keep your connections" = "Ihre Verbindungen beibehalten"; @@ -2163,6 +2235,9 @@ /* No comment provided by engineer. */ "Live messages" = "Live Nachrichten"; +/* No comment provided by engineer. */ +"Local" = "Lokal"; + /* No comment provided by engineer. */ "Local name" = "Lokaler Name"; @@ -2188,7 +2263,7 @@ "Make sure %@ server addresses are in correct format, line separated and are not duplicated (%@)." = "Stellen Sie sicher, dass die %@-Server-Adressen das richtige Format haben, zeilenweise getrennt und nicht doppelt vorhanden sind (%@)."; /* No comment provided by engineer. */ -"Make sure WebRTC ICE server addresses are in correct format, line separated and are not duplicated." = "Stellen Sie sicher, dass die WebRTC ICE-Server Adressen das richtige Format haben, zeilenweise angeordnet und nicht doppelt vorhanden sind."; +"Make sure WebRTC ICE server addresses are in correct format, line separated and are not duplicated." = "Stellen Sie sicher, dass die WebRTC ICE-Server Adressen das richtige Format haben, zeilenweise getrennt und nicht doppelt vorhanden sind."; /* No comment provided by engineer. */ "Many people asked: *if SimpleX has no user identifiers, how can it deliver messages?*" = "Viele Menschen haben gefragt: *Wie kann SimpleX Nachrichten zustellen, wenn es keine Benutzerkennungen gibt?*"; @@ -2217,6 +2292,9 @@ /* No comment provided by engineer. */ "Member" = "Mitglied"; +/* profile update event chat item */ +"member %@ changed to %@" = "Der Mitgliedsname %1$@ wurde auf %2$@ geändert"; + /* rcv group event chat item */ "member connected" = "ist der Gruppe beigetreten"; @@ -2334,6 +2412,9 @@ /* No comment provided by engineer. */ "never" = "nie"; +/* No comment provided by engineer. */ +"New chat" = "Neuer Chat"; + /* notification */ "New contact request" = "Neue Kontaktanfrage"; @@ -2398,7 +2479,7 @@ "No group!" = "Die Gruppe wurde nicht gefunden!"; /* No comment provided by engineer. */ -"No history" = "Keine Vergangenheit"; +"No history" = "Kein Nachrichtenverlauf"; /* No comment provided by engineer. */ "No permission to record voice message" = "Keine Berechtigung für das Aufnehmen von Sprachnachrichten"; @@ -2432,9 +2513,6 @@ /* No comment provided by engineer. */ "Off" = "Aus"; -/* No comment provided by engineer. */ -"Off (Local)" = "Aus (Lokal)"; - /* feature offered item */ "offered %@" = "angeboten %@"; @@ -2444,6 +2522,9 @@ /* No comment provided by engineer. */ "Ok" = "Ok"; +/* No comment provided by engineer. */ +"OK" = "OK"; + /* No comment provided by engineer. */ "Old database" = "Alte Datenbank"; @@ -2481,7 +2562,7 @@ "Only you can add message reactions." = "Nur Sie können Reaktionen auf Nachrichten geben."; /* No comment provided by engineer. */ -"Only you can irreversibly delete messages (your contact can mark them for deletion)." = "Nur Sie können Nachrichten unwiederbringlich löschen (Ihr Kontakt kann sie zum Löschen markieren)."; +"Only you can irreversibly delete messages (your contact can mark them for deletion). (24 hours)" = "Nur Sie können Nachrichten unwiederbringlich löschen (Ihr Kontakt kann sie zum Löschen markieren). (24 Stunden)"; /* No comment provided by engineer. */ "Only you can make calls." = "Nur Sie können Anrufe tätigen."; @@ -2496,7 +2577,7 @@ "Only your contact can add message reactions." = "Nur Ihr Kontakt kann Reaktionen auf Nachrichten geben."; /* No comment provided by engineer. */ -"Only your contact can irreversibly delete messages (you can mark them for deletion)." = "Nur Ihr Kontakt kann Nachrichten unwiederbringlich löschen (Sie können sie zum Löschen markieren)."; +"Only your contact can irreversibly delete messages (you can mark them for deletion). (24 hours)" = "Nur Ihr Kontakt kann Nachrichten unwiederbringlich löschen (Sie können sie zum Löschen markieren). (24 Stunden)"; /* No comment provided by engineer. */ "Only your contact can make calls." = "Nur Ihr Kontakt kann Anrufe tätigen."; @@ -2529,7 +2610,13 @@ "Open-source protocol and code – anybody can run the servers." = "Open-Source-Protokoll und -Code – Jede Person kann ihre eigenen Server aufsetzen und nutzen."; /* No comment provided by engineer. */ -"Opening database…" = "Öffne Datenbank …"; +"Opening app…" = "App wird geöffnet…"; + +/* No comment provided by engineer. */ +"Or scan QR code" = "Oder den QR-Code scannen"; + +/* No comment provided by engineer. */ +"Or show this code" = "Oder diesen QR-Code anzeigen"; /* member role */ "owner" = "Eigentümer"; @@ -2552,8 +2639,8 @@ /* No comment provided by engineer. */ "Password to show" = "Passwort anzeigen"; -/* No comment provided by engineer. */ -"Paste" = "Einfügen"; +/* past/unknown group member */ +"Past member %@" = "Ehemaliges Mitglied %@"; /* No comment provided by engineer. */ "Paste desktop address" = "Desktop-Adresse einfügen"; @@ -2562,10 +2649,10 @@ "Paste image" = "Bild einfügen"; /* No comment provided by engineer. */ -"Paste received link" = "Fügen Sie den erhaltenen Link ein"; +"Paste link to connect!" = "Zum Verbinden den Link einfügen!"; -/* placeholder */ -"Paste the link you received to connect with your contact." = "Um sich mit Ihrem Kontakt zu verbinden, fügen Sie den erhaltenen Link in das Feld unten ein."; +/* No comment provided by engineer. */ +"Paste the link you received" = "Fügen Sie den erhaltenen Link ein"; /* No comment provided by engineer. */ "peer-to-peer" = "Peer-to-Peer"; @@ -2597,6 +2684,9 @@ /* No comment provided by engineer. */ "Please check yours and your contact preferences." = "Bitte überprüfen sie sowohl Ihre, als auch die Präferenzen Ihres Kontakts."; +/* No comment provided by engineer. */ +"Please contact developers.\nError: %@" = "Bitte nehmen Sie Kontakt mit den Entwicklern auf.\nFehler: %@"; + /* No comment provided by engineer. */ "Please contact group admin." = "Bitte kontaktieren Sie den Gruppen-Administrator."; @@ -2648,6 +2738,9 @@ /* No comment provided by engineer. */ "Private filenames" = "Neutrale Dateinamen"; +/* name of notes to self */ +"Private notes" = "Private Notizen"; + /* No comment provided by engineer. */ "Profile and server connections" = "Profil und Serververbindungen"; @@ -2720,6 +2813,9 @@ /* No comment provided by engineer. */ "Read more in [User Guide](https://simplex.chat/docs/guide/app-settings.html#your-simplex-contact-address)." = "Mehr dazu in der [Benutzeranleitung](https://simplex.chat/docs/guide/app-settings.html#your-simplex-contact-address) lesen."; +/* No comment provided by engineer. */ +"Read more in [User Guide](https://simplex.chat/docs/guide/chat-profiles.html#incognito-mode)." = "Lesen Sie mehr dazu im [Benutzerhandbuch](https://simplex.chat/docs/guide/chat-profiles.html#incognito-mode)."; + /* No comment provided by engineer. */ "Read more in [User Guide](https://simplex.chat/docs/guide/readme.html#connect-to-friends)." = "Mehr dazu in der [Benutzeranleitung](https://simplex.chat/docs/guide/readme.html#connect-to-friends) lesen."; @@ -2759,6 +2855,9 @@ /* No comment provided by engineer. */ "Receiving via" = "Empfangen über"; +/* No comment provided by engineer. */ +"Recent history and improved [directory bot](simplex:/contact#/?v=1-4&smp=smp%3A%2F%2Fu2dS9sG8nMNURyZwqASV4yROM28Er0luVTx5X1CsMrU%3D%40smp4.simplex.im%2FeXSPwqTkKyDO3px4fLf1wx3MvPdjdLW3%23%2F%3Fv%3D1-2%26dh%3DMCowBQYDK2VuAyEAaiv6MkMH44L2TcYrt_CsX3ZvM11WgbMEUn0hkIKTOho%253D%26srv%3Do5vmywmrnaxalvz6wi3zicyftgio6psuvyniis6gco6bp6ekl4cqj4id.onion)." = "Aktueller Nachrichtenverlauf und verbesserter [Gruppenverzeichnis-Bot](simplex:/contact#/?v=1-4&smp=smp%3A%2F%2Fu2dS9sG8nMNURyZwqASV4yROM28Er0luVTx5X1CsMrU%3D%40smp4.simplex.im%2FeXSPwqTkKyDO3px4fLf1wx3MvPdjdLW3%23%2F%3Fv%3D1-2%26dh%3DMCowBQYDK2VuAyEAaiv6MkMH44L2TcYrt_CsX3ZvM11WgbMEUn0hkIKTOho%253D%26srv%3Do5vmywmrnaxalvz6wi3zicyftgio6psuvyniis6gco6bp6ekl4cqj4id.onion)."; + /* No comment provided by engineer. */ "Recipients see updates as you type them." = "Die Empfänger sehen Nachrichtenaktualisierungen, während Sie sie eingeben."; @@ -2813,6 +2912,12 @@ /* rcv group event chat item */ "removed %@" = "hat %@ aus der Gruppe entfernt"; +/* profile update event chat item */ +"removed contact address" = "Kontaktadresse wurde entfernt"; + +/* profile update event chat item */ +"removed profile picture" = "Profil-Bild wurde entfernt"; + /* rcv group event chat item */ "removed you" = "hat Sie aus der Gruppe entfernt"; @@ -2864,6 +2969,9 @@ /* No comment provided by engineer. */ "Restore database error" = "Fehler bei der Wiederherstellung der Datenbank"; +/* No comment provided by engineer. */ +"Retry" = "Wiederholen"; + /* chat item action */ "Reveal" = "Aufdecken"; @@ -2933,6 +3041,9 @@ /* No comment provided by engineer. */ "Save welcome message?" = "Begrüßungsmeldung speichern?"; +/* message info title */ +"Saved message" = "Gespeicherte Nachricht"; + /* No comment provided by engineer. */ "Saved WebRTC ICE servers will be removed" = "Gespeicherte WebRTC ICE-Server werden entfernt"; @@ -2954,6 +3065,12 @@ /* No comment provided by engineer. */ "Search" = "Suche"; +/* No comment provided by engineer. */ +"Search bar accepts invitation links." = "Von der Suchleiste werden Einladungslinks akzeptiert."; + +/* No comment provided by engineer. */ +"Search or paste SimpleX link" = "Suchen oder fügen Sie den SimpleX-Link ein"; + /* network option */ "sec" = "sek"; @@ -3032,6 +3149,9 @@ /* No comment provided by engineer. */ "Send them from gallery or custom keyboards." = "Senden Sie diese aus dem Fotoalbum oder von individuellen Tastaturen."; +/* No comment provided by engineer. */ +"Send up to 100 last messages to new members." = "Bis zu 100 der letzten Nachrichten an neue Gruppenmitglieder senden."; + /* No comment provided by engineer. */ "Sender cancelled file transfer." = "Der Absender hat die Dateiübertragung abgebrochen."; @@ -3104,6 +3224,12 @@ /* No comment provided by engineer. */ "Set it instead of system authentication." = "Anstelle der System-Authentifizierung festlegen."; +/* profile update event chat item */ +"set new contact address" = "Neue Kontaktadresse wurde festgelegt"; + +/* profile update event chat item */ +"set new profile picture" = "Neues Profil-Bild wurde festgelegt"; + /* No comment provided by engineer. */ "Set passcode" = "Zugangscode einstellen"; @@ -3135,7 +3261,7 @@ "Share link" = "Link teilen"; /* No comment provided by engineer. */ -"Share one-time invitation link" = "Einmal-Einladungslink teilen"; +"Share this 1-time invite link" = "Teilen Sie diesen Einmal-Einladungslink"; /* No comment provided by engineer. */ "Share with contacts" = "Mit Kontakten teilen"; @@ -3213,10 +3339,10 @@ "Somebody" = "Jemand"; /* No comment provided by engineer. */ -"Start a new chat" = "Starten Sie einen neuen Chat"; +"Start chat" = "Starten Sie den Chat"; /* No comment provided by engineer. */ -"Start chat" = "Starten Sie den Chat"; +"Start chat?" = "Chat starten?"; /* No comment provided by engineer. */ "Start migration" = "Starten Sie die Migration"; @@ -3276,19 +3402,25 @@ "Tap button " = "Schaltfläche antippen "; /* No comment provided by engineer. */ -"Tap to activate profile." = "Tippen Sie auf das Profil um es zu aktivieren."; +"Tap to activate profile." = "Zum Aktivieren des Profils tippen."; /* No comment provided by engineer. */ -"Tap to Connect" = "Zum Verbinden antippen"; +"Tap to Connect" = "Zum Verbinden tippen"; /* No comment provided by engineer. */ "Tap to join" = "Zum Beitreten tippen"; /* No comment provided by engineer. */ -"Tap to join incognito" = "Tippen, um Inkognito beizutreten"; +"Tap to join incognito" = "Zum Inkognito beitreten tippen"; /* No comment provided by engineer. */ -"Tap to start a new chat" = "Tippen, um einen neuen Chat zu starten"; +"Tap to paste link" = "Zum Link einfügen tippen"; + +/* No comment provided by engineer. */ +"Tap to scan" = "Zum Scannen tippen"; + +/* No comment provided by engineer. */ +"Tap to start a new chat" = "Zum Starten eines neuen Chats tippen"; /* No comment provided by engineer. */ "TCP connection timeout" = "Timeout der TCP-Verbindung"; @@ -3332,6 +3464,9 @@ /* No comment provided by engineer. */ "The attempt to change database passphrase was not completed." = "Die Änderung des Datenbank-Passworts konnte nicht abgeschlossen werden."; +/* No comment provided by engineer. */ +"The code you scanned is not a SimpleX link QR code." = "Der von Ihnen gescannte Code ist kein SimpleX-Link-QR-Code."; + /* No comment provided by engineer. */ "The connection you accepted will be cancelled!" = "Die von Ihnen akzeptierte Verbindung wird abgebrochen!"; @@ -3372,17 +3507,14 @@ "The sender will NOT be notified" = "Der Absender wird NICHT benachrichtigt"; /* No comment provided by engineer. */ -"The servers for new connections of your current chat profile **%@**." = "Server der neuen Verbindungen von Ihrem aktuellen Chat-Profil **%@**."; +"The servers for new connections of your current chat profile **%@**." = "Mögliche Server für neue Verbindungen von Ihrem aktuellen Chat-Profil **%@**."; + +/* No comment provided by engineer. */ +"The text you pasted is not a SimpleX link." = "Der von Ihnen eingefügte Text ist kein SimpleX-Link."; /* No comment provided by engineer. */ "Theme" = "Design"; -/* No comment provided by engineer. */ -"There should be at least one user profile." = "Es muss mindestens ein Benutzer-Profil vorhanden sein."; - -/* No comment provided by engineer. */ -"There should be at least one visible user profile." = "Es muss mindestens ein sichtbares Benutzer-Profil vorhanden sein."; - /* No comment provided by engineer. */ "These settings are for your current profile **%@**." = "Diese Einstellungen betreffen Ihr aktuelles Profil **%@**."; @@ -3404,6 +3536,9 @@ /* No comment provided by engineer. */ "This device name" = "Dieser Gerätename"; +/* No comment provided by engineer. */ +"This display name is invalid. Please choose another name." = "Der Anzeigename ist ungültig. Bitte wählen Sie einen anderen Namen."; + /* No comment provided by engineer. */ "This group has over %lld members, delivery receipts are not sent." = "Es werden keine Empfangsbestätigungen gesendet, da diese Gruppe über %lld Mitglieder hat."; @@ -3465,10 +3600,10 @@ "Trying to connect to the server used to receive messages from this contact." = "Versuche die Verbindung mit dem Server aufzunehmen, der für den Empfang von Nachrichten mit diesem Kontakt genutzt wird."; /* No comment provided by engineer. */ -"Turn off" = "Abschalten"; +"Turkish interface" = "Türkische Bedienoberfläche"; /* No comment provided by engineer. */ -"Turn off notifications?" = "Benachrichtigungen abschalten?"; +"Turn off" = "Abschalten"; /* No comment provided by engineer. */ "Turn on" = "Einschalten"; @@ -3479,12 +3614,21 @@ /* No comment provided by engineer. */ "Unblock" = "Freigeben"; +/* No comment provided by engineer. */ +"Unblock for all" = "Für Alle freigeben"; + /* No comment provided by engineer. */ "Unblock member" = "Mitglied freigeben"; +/* No comment provided by engineer. */ +"Unblock member for all?" = "Mitglied für Alle freigeben?"; + /* No comment provided by engineer. */ "Unblock member?" = "Mitglied freigeben?"; +/* rcv group event chat item */ +"unblocked %@" = "%@ wurde freigegeben"; + /* item status description */ "Unexpected error: %@" = "Unerwarteter Fehler: %@"; @@ -3518,6 +3662,9 @@ /* No comment provided by engineer. */ "Unknown error" = "Unbekannter Fehler"; +/* No comment provided by engineer. */ +"unknown status" = "unbekannter Gruppenmitglieds-Status"; + /* No comment provided by engineer. */ "Unless you use iOS call interface, enable Do Not Disturb mode to avoid interruptions." = "Aktivieren Sie den Modus \"Bitte nicht stören\", um Unterbrechungen zu vermeiden, es sei denn, Sie verwenden die iOS Anrufschnittstelle."; @@ -3542,6 +3689,9 @@ /* No comment provided by engineer. */ "Unread" = "Ungelesen"; +/* No comment provided by engineer. */ +"Up to 100 last messages are sent to new members." = "Bis zu 100 der letzten Nachrichten werden an neue Mitglieder gesendet."; + /* No comment provided by engineer. */ "Update" = "Aktualisieren"; @@ -3560,6 +3710,9 @@ /* rcv group event chat item */ "updated group profile" = "Aktualisiertes Gruppenprofil"; +/* profile update event chat item */ +"updated profile" = "Das Profil wurde aktualisiert"; + /* No comment provided by engineer. */ "Updating settings will re-connect the client to all servers." = "Die Aktualisierung der Einstellungen wird den Client wieder mit allen Servern verbinden."; @@ -3593,6 +3746,9 @@ /* No comment provided by engineer. */ "Use new incognito profile" = "Nutzen Sie das neue Inkognito-Profil"; +/* No comment provided by engineer. */ +"Use only local notifications?" = "Nur lokale Benachrichtigungen nutzen?"; + /* No comment provided by engineer. */ "Use server" = "Server nutzen"; @@ -3665,6 +3821,9 @@ /* No comment provided by engineer. */ "View security code" = "Schauen Sie sich den Sicherheitscode an"; +/* chat feature */ +"Visible history" = "Sichtbarer Nachrichtenverlauf"; + /* No comment provided by engineer. */ "Voice message…" = "Sprachnachrichten…"; @@ -3728,9 +3887,15 @@ /* No comment provided by engineer. */ "When you share an incognito profile with somebody, this profile will be used for the groups they invite you to." = "Wenn Sie ein Inkognito-Profil mit Jemandem teilen, wird dieses Profil auch für die Gruppen verwendet, für die Sie von diesem Kontakt eingeladen werden."; +/* No comment provided by engineer. */ +"With encrypted files and media." = "Mit verschlüsselten Dateien und Medien."; + /* No comment provided by engineer. */ "With optional welcome message." = "Mit optionaler Begrüßungsmeldung."; +/* No comment provided by engineer. */ +"With reduced battery usage." = "Mit reduziertem Akkuverbrauch."; + /* No comment provided by engineer. */ "Wrong database passphrase" = "Falsches Datenbank-Passwort"; @@ -3744,7 +3909,7 @@ "yes" = "Ja"; /* No comment provided by engineer. */ -"You" = "Ihre Daten"; +"You" = "Profil"; /* No comment provided by engineer. */ "You accepted connection" = "Sie haben die Verbindung akzeptiert"; @@ -3791,11 +3956,11 @@ /* No comment provided by engineer. */ "you are observer" = "Sie sind Beobachter"; -/* No comment provided by engineer. */ -"You can accept calls from lock screen, without device and app authentication." = "Sie können Anrufe ohne Geräte- und App-Authentifizierung vom Sperrbildschirm aus annehmen."; +/* snd group event chat item */ +"you blocked %@" = "Sie haben %@ blockiert"; /* No comment provided by engineer. */ -"You can also connect by clicking the link. If it opens in the browser, click **Open in mobile app** button." = "Sie können sich auch verbinden, indem Sie auf den Link klicken. Wenn er im Browser geöffnet wird, klicken Sie auf die Schaltfläche **In mobiler App öffnen**."; +"You can accept calls from lock screen, without device and app authentication." = "Sie können Anrufe ohne Geräte- und App-Authentifizierung vom Sperrbildschirm aus annehmen."; /* No comment provided by engineer. */ "You can create it later" = "Sie können dies später erstellen"; @@ -3809,6 +3974,9 @@ /* No comment provided by engineer. */ "You can hide or mute a user profile - swipe it to the right." = "Sie können ein Benutzerprofil verbergen oder stummschalten - wischen Sie es nach rechts."; +/* No comment provided by engineer. */ +"You can make it visible to your SimpleX contacts via Settings." = "Sie können sie über Einstellungen für Ihre SimpleX-Kontakte sichtbar machen."; + /* notification body */ "You can now send messages to %@" = "Sie können nun Nachrichten an %@ versenden"; @@ -3833,14 +4001,17 @@ /* No comment provided by engineer. */ "You can use markdown to format messages:" = "Um Nachrichteninhalte zu formatieren, können Sie Markdowns verwenden:"; +/* No comment provided by engineer. */ +"You can view invitation link again in connection details." = "Den Einladungslink können Sie in den Details der Verbindung nochmals sehen."; + /* No comment provided by engineer. */ "You can't send messages!" = "Sie können keine Nachrichten versenden!"; /* chat item text */ -"you changed address" = "Sie haben die Adresse gewechselt"; +"you changed address" = "Die Empfängeradresse wurde gewechselt"; /* chat item text */ -"you changed address for %@" = "Sie haben die Adresse für %@ gewechselt"; +"you changed address for %@" = "Die Empfängeradresse für %@ wurde gewechselt"; /* snd group event chat item */ "you changed role for yourself to %@" = "Sie haben Ihre eigene Rolle auf %@ geändert"; @@ -3899,6 +4070,9 @@ /* chat list item description */ "you shared one-time link incognito" = "Sie haben Inkognito einen Einmal-Link geteilt"; +/* snd group event chat item */ +"you unblocked %@" = "Sie haben %@ freigegeben"; + /* No comment provided by engineer. */ "You will be connected to group when the group host's device is online, please wait or check later!" = "Sie werden mit der Gruppe verbunden, sobald das Endgerät des Gruppen-Hosts online ist. Bitte warten oder schauen Sie später nochmal nach!"; @@ -3921,10 +4095,10 @@ "You will still receive calls and notifications from muted profiles when they are active." = "Sie können Anrufe und Benachrichtigungen auch von stummgeschalteten Profilen empfangen, solange diese aktiv sind."; /* No comment provided by engineer. */ -"You will stop receiving messages from this group. Chat history will be preserved." = "Sie werden von dieser Gruppe keine Nachrichten mehr erhalten. Der Chatverlauf wird beibehalten."; +"You will stop receiving messages from this group. Chat history will be preserved." = "Sie werden von dieser Gruppe keine Nachrichten mehr erhalten. Der Nachrichtenverlauf wird beibehalten."; /* No comment provided by engineer. */ -"You won't lose your contacts if you later delete your address." = "Sie werden Ihre mit dieser Adresse verbundenen Kontakte nicht verlieren, wenn Sie diese Adresse später löschen."; +"You won't lose your contacts if you later delete your address." = "Sie werden Ihre damit verbundenen Kontakte nicht verlieren, wenn Sie diese Adresse später löschen."; /* No comment provided by engineer. */ "you: " = "Sie: "; @@ -3959,9 +4133,6 @@ /* No comment provided by engineer. */ "Your contacts can allow full message deletion." = "Ihre Kontakte können die unwiederbringliche Löschung von Nachrichten erlauben."; -/* No comment provided by engineer. */ -"Your contacts in SimpleX will see it.\nYou can change it in Settings." = "Ihre Kontakte in SimpleX werden es sehen.\nSie können es in den Einstellungen ändern."; - /* No comment provided by engineer. */ "Your contacts will remain connected." = "Ihre Kontakte bleiben verbunden."; @@ -4002,7 +4173,7 @@ "Your server address" = "Ihre Serveradresse"; /* No comment provided by engineer. */ -"Your settings" = "Ihre Einstellungen"; +"Your settings" = "Einstellungen"; /* No comment provided by engineer. */ "Your SimpleX address" = "Ihre SimpleX-Adresse"; diff --git a/apps/ios/es.lproj/Localizable.strings b/apps/ios/es.lproj/Localizable.strings index d9b14eddbd..25ca04f24d 100644 --- a/apps/ios/es.lproj/Localizable.strings +++ b/apps/ios/es.lproj/Localizable.strings @@ -25,6 +25,9 @@ /* No comment provided by engineer. */ "- more stable message delivery.\n- a bit better groups.\n- and more!" = "- entrega de mensajes más estable.\n- grupos un poco mejores.\n- ¡y más!"; +/* No comment provided by engineer. */ +"- optionally notify deleted contacts.\n- profile names with spaces.\n- and more!" = "- notificar opcionalmente a los contactos eliminados.\n- nombres de perfil con espacios.\n- ¡...y más!"; + /* No comment provided by engineer. */ "- voice messages up to 5 minutes.\n- custom time to disappear.\n- editing history." = "- mensajes de voz de hasta 5 minutos.\n- tiempo personalizado para mensajes temporales.\n- historial de edición."; @@ -43,6 +46,12 @@ /* No comment provided by engineer. */ "(" = "("; +/* No comment provided by engineer. */ +"(new)" = "(nuevo)"; + +/* No comment provided by engineer. */ +"(this device v%@)" = "(este dispositivo v%@)"; + /* No comment provided by engineer. */ ")" = ")"; @@ -55,11 +64,14 @@ /* No comment provided by engineer. */ "[Star on GitHub](https://github.com/simplex-chat/simplex-chat)" = "[Estrella en GitHub](https://github.com/simplex-chat/simplex-chat)"; +/* No comment provided by engineer. */ +"**Add contact**: to create a new invitation link, or connect via a link you received." = "**Añadir contacto**: crea un enlace de invitación nuevo o usa un enlace recibido."; + /* No comment provided by engineer. */ "**Add new contact**: to create your one-time QR Code for your contact." = "**Añadir nuevo contacto**: para crear tu código QR o enlace de un uso para tu contacto."; /* No comment provided by engineer. */ -"**Create link / QR code** for your contact to use." = "**Crea enlace / código QR** para que tu contacto lo use."; +"**Create group**: to create a new group." = "**Crear grupo**: crea un grupo nuevo."; /* No comment provided by engineer. */ "**e2e encrypted** audio call" = "Llamada con **cifrado de extremo a extremo **"; @@ -73,18 +85,12 @@ /* No comment provided by engineer. */ "**Most private**: do not use SimpleX Chat notifications server, check messages periodically in the background (depends on how often you use the app)." = "**Más privado**: no se usa el servidor de notificaciones de SimpleX Chat, los mensajes se comprueban periódicamente en segundo plano (dependiendo de la frecuencia con la que utilices la aplicación)."; -/* No comment provided by engineer. */ -"**Paste received link** or open it in the browser and tap **Open in mobile app**." = "**Pega el enlace recibido** o ábrelo en el navegador y pulsa **Abrir en aplicación móvil**."; - /* No comment provided by engineer. */ "**Please note**: you will NOT be able to recover or change passphrase if you lose it." = "**Atención**: NO podrás recuperar o cambiar la contraseña si la pierdes."; /* No comment provided by engineer. */ "**Recommended**: device token and notifications are sent to SimpleX Chat notification server, but not the message content, size or who it is from." = "**Recomendado**: el token del dispositivo y las notificaciones se envían al servidor de notificaciones de SimpleX Chat, pero no el contenido del mensaje, su tamaño o su procedencia."; -/* No comment provided by engineer. */ -"**Scan QR code**: to connect to your contact in person or via video call." = "**Escanear código QR**: en persona para conectarte con tu contacto, o por videollamada."; - /* No comment provided by engineer. */ "**Warning**: Instant push notifications require passphrase saved in Keychain." = "**Advertencia**: Las notificaciones automáticas instantáneas requieren una contraseña guardada en Keychain."; @@ -118,12 +124,18 @@ /* No comment provided by engineer. */ "%@ %@" = "%@ %@"; +/* No comment provided by engineer. */ +"%@ and %@" = "%@ y %@"; + /* No comment provided by engineer. */ "%@ and %@ connected" = "%@ y %@ conectados"; /* copied message info, <sender> at <time> */ "%@ at %@:" = "%1$@ a las %2$@:"; +/* No comment provided by engineer. */ +"%@ connected" = "%@ conectado"; + /* notification title */ "%@ is connected!" = "%@ ¡está conectado!"; @@ -139,6 +151,9 @@ /* notification title */ "%@ wants to connect!" = "¡ %@ quiere contactar!"; +/* No comment provided by engineer. */ +"%@, %@ and %lld members" = "%@, %@ y %lld miembro(s) más"; + /* No comment provided by engineer. */ "%@, %@ and %lld other members connected" = "%@, %@ y %lld miembros más conectados"; @@ -178,9 +193,21 @@ /* No comment provided by engineer. */ "%lld file(s) with total size of %@" = "%lld archivo(s) con un tamaño total de %@"; +/* No comment provided by engineer. */ +"%lld group events" = "%lld evento(s) de grupo"; + /* No comment provided by engineer. */ "%lld members" = "%lld miembros"; +/* No comment provided by engineer. */ +"%lld messages blocked" = "%lld mensaje(s) bloqueado(s)"; + +/* No comment provided by engineer. */ +"%lld messages marked deleted" = "%lld mensaje(s) marcado(s) eliminado(s)"; + +/* No comment provided by engineer. */ +"%lld messages moderated by %@" = "%lld mensaje(s) moderado(s) por %@"; + /* No comment provided by engineer. */ "%lld minutes" = "%lld minutos"; @@ -229,6 +256,9 @@ /* No comment provided by engineer. */ "~strike~" = "\\~strike~"; +/* time to disappear */ +"0 sec" = "0 seg"; + /* No comment provided by engineer. */ "0s" = "0s"; @@ -247,9 +277,6 @@ /* time interval */ "1 week" = "una semana"; -/* No comment provided by engineer. */ -"1-time link" = "Enlace un uso"; - /* No comment provided by engineer. */ "5 minutes" = "5 minutos"; @@ -278,10 +305,10 @@ "Abort" = "Cancelar"; /* No comment provided by engineer. */ -"Abort changing address" = "Cancelar cambio de dirección"; +"Abort changing address" = "Cancelar cambio de servidor"; /* No comment provided by engineer. */ -"Abort changing address?" = "¿Cancelar el cambio de dirección?"; +"Abort changing address?" = "¿Cancelar el cambio de servidor?"; /* No comment provided by engineer. */ "About SimpleX" = "Acerca de SimpleX"; @@ -317,6 +344,9 @@ /* No comment provided by engineer. */ "Add address to your profile, so that your contacts can share it with other people. Profile update will be sent to your contacts." = "Añade la dirección a tu perfil para que tus contactos puedan compartirla con otros. La actualización del perfil se enviará a tus contactos."; +/* No comment provided by engineer. */ +"Add contact" = "Añadir contacto"; + /* No comment provided by engineer. */ "Add preset servers" = "Añadir servidores predefinidos"; @@ -371,6 +401,9 @@ /* No comment provided by engineer. */ "All messages will be deleted - this cannot be undone! The messages will be deleted ONLY for you." = "Se eliminarán todos los mensajes SOLO para tí. ¡No podrá deshacerse!"; +/* No comment provided by engineer. */ +"All new messages from %@ will be hidden!" = "¡Los mensajes nuevos de %@ estarán ocultos!"; + /* No comment provided by engineer. */ "All your contacts will remain connected." = "Todos tus contactos permanecerán conectados."; @@ -387,13 +420,13 @@ "Allow disappearing messages only if your contact allows it to you." = "Se permiten los mensajes temporales pero sólo si tu contacto también los permite para tí."; /* No comment provided by engineer. */ -"Allow irreversible message deletion only if your contact allows it to you." = "Se permite la eliminación irreversible de mensajes pero sólo si tu contacto también la permite para tí."; +"Allow irreversible message deletion only if your contact allows it to you. (24 hours)" = "Se permite la eliminación irreversible de mensajes pero sólo si tu contacto también la permite para tí. (24 horas)"; /* No comment provided by engineer. */ "Allow message reactions only if your contact allows them." = "Se permiten las reacciones a los mensajes pero sólo si tu contacto también las permite."; /* No comment provided by engineer. */ -"Allow message reactions." = "Permitir reacciones a los mensajes."; +"Allow message reactions." = "Se permiten reacciones a los mensajes."; /* No comment provided by engineer. */ "Allow sending direct messages to members." = "Se permiten mensajes directos entre miembros."; @@ -402,7 +435,7 @@ "Allow sending disappearing messages." = "Permites el envío de mensajes temporales."; /* No comment provided by engineer. */ -"Allow to irreversibly delete sent messages." = "Se permite la eliminación irreversible de mensajes."; +"Allow to irreversibly delete sent messages. (24 hours)" = "Se permite la eliminación irreversible de mensajes. (24 horas)"; /* No comment provided by engineer. */ "Allow to send files and media." = "Se permite enviar archivos y multimedia."; @@ -423,7 +456,7 @@ "Allow your contacts to call you." = "Permites que tus contactos puedan llamarte."; /* No comment provided by engineer. */ -"Allow your contacts to irreversibly delete sent messages." = "Permites a tus contactos eliminar irreversiblemente los mensajes enviados."; +"Allow your contacts to irreversibly delete sent messages. (24 hours)" = "Permites a tus contactos eliminar irreversiblemente los mensajes enviados. (24 horas)"; /* No comment provided by engineer. */ "Allow your contacts to send disappearing messages." = "Permites a tus contactos enviar mensajes temporales."; @@ -434,6 +467,12 @@ /* No comment provided by engineer. */ "Already connected?" = "¿Ya está conectado?"; +/* No comment provided by engineer. */ +"Already connecting!" = "¡Ya en proceso de conexión!"; + +/* No comment provided by engineer. */ +"Already joining the group!" = "¡Ya en proceso de unirte al grupo!"; + /* pref value */ "always" = "siempre"; @@ -443,6 +482,9 @@ /* No comment provided by engineer. */ "An empty chat profile with the provided name is created, and the app opens as usual." = "Se creará un perfil vacío con el nombre proporcionado, y la aplicación se abrirá como de costumbre."; +/* No comment provided by engineer. */ +"and %lld other events" = "y %lld evento(s) más"; + /* No comment provided by engineer. */ "Answer call" = "Responder llamada"; @@ -500,6 +542,9 @@ /* No comment provided by engineer. */ "Authentication unavailable" = "Autenticación no disponible"; +/* member role */ +"author" = "autor"; + /* No comment provided by engineer. */ "Auto-accept" = "Auto aceptar"; @@ -512,6 +557,9 @@ /* No comment provided by engineer. */ "Back" = "Volver"; +/* No comment provided by engineer. */ +"Bad desktop address" = "Dirección ordenador incorrecta"; + /* integrity error chat item */ "bad message hash" = "hash de mensaje erróneo"; @@ -524,9 +572,27 @@ /* No comment provided by engineer. */ "Bad message ID" = "ID de mensaje incorrecto"; +/* No comment provided by engineer. */ +"Better groups" = "Grupos mejorados"; + /* No comment provided by engineer. */ "Better messages" = "Mensajes mejorados"; +/* No comment provided by engineer. */ +"Block" = "Bloquear"; + +/* No comment provided by engineer. */ +"Block group members" = "Bloquear miembros del grupo"; + +/* No comment provided by engineer. */ +"Block member" = "Bloquear miembro"; + +/* No comment provided by engineer. */ +"Block member?" = "¿Bloquear miembro?"; + +/* No comment provided by engineer. */ +"blocked" = "bloqueado"; + /* No comment provided by engineer. */ "bold" = "negrita"; @@ -534,7 +600,7 @@ "Both you and your contact can add message reactions." = "Tanto tú como tu contacto podéis añadir reacciones a los mensajes."; /* No comment provided by engineer. */ -"Both you and your contact can irreversibly delete sent messages." = "Tanto tú como tu contacto podéis eliminar de forma irreversible los mensajes enviados."; +"Both you and your contact can irreversibly delete sent messages. (24 hours)" = "Tanto tú como tu contacto podéis eliminar de forma irreversible los mensajes enviados. (24 horas)"; /* No comment provided by engineer. */ "Both you and your contact can make calls." = "Tanto tú como tu contacto podéis realizar llamadas."; @@ -567,13 +633,13 @@ "Calls" = "Llamadas"; /* No comment provided by engineer. */ -"Can't delete user profile!" = "¡No se puede eliminar el perfil!"; +"Camera not available" = "Cámara no disponible"; /* No comment provided by engineer. */ "Can't invite contact!" = "¡No se puede invitar el contacto!"; /* No comment provided by engineer. */ -"Can't invite contacts!" = "¡No se puede invitar a los contactos!"; +"Can't invite contacts!" = "¡No se pueden invitar contactos!"; /* No comment provided by engineer. */ "Cancel" = "Cancelar"; @@ -597,7 +663,7 @@ "Change lock mode" = "Cambiar el modo de bloqueo"; /* No comment provided by engineer. */ -"Change member role?" = "¿Cambiar el rol del miembro?"; +"Change member role?" = "¿Cambiar rol?"; /* authentication reason */ "Change passcode" = "Cambiar código de acceso"; @@ -619,7 +685,7 @@ "Change self-destruct passcode" = "Cambiar código autodestrucción"; /* chat item text */ -"changed address for you" = "el servidor de envío ha cambiado para tí"; +"changed address for you" = "ha cambiado tu servidor de envío"; /* rcv group event chat item */ "changed role of %@ to %@" = "rol cambiado de %1$@ a %2$@"; @@ -628,10 +694,10 @@ "changed your role to %@" = "ha cambiado tu rol a %@"; /* chat item text */ -"changing address for %@…" = "cambiando dirección para %@…"; +"changing address for %@…" = "cambiando el servidor para %@…"; /* chat item text */ -"changing address…" = "cambiando dirección…"; +"changing address…" = "cambiando de servidor…"; /* No comment provided by engineer. */ "Chat archive" = "Archivo del chat"; @@ -654,6 +720,9 @@ /* No comment provided by engineer. */ "Chat is stopped" = "Chat está detenido"; +/* No comment provided by engineer. */ +"Chat is stopped. If you already used this database on another device, you should transfer it back before starting chat." = "Chat está detenido. Si estás usando esta base de datos en otro dispositivo, deberías transferirla de vuelta antes de iniciarlo."; + /* No comment provided by engineer. */ "Chat preferences" = "Preferencias de Chat"; @@ -720,27 +789,51 @@ /* server test step */ "Connect" = "Conectar"; +/* No comment provided by engineer. */ +"Connect automatically" = "Conectar automáticamente"; + /* No comment provided by engineer. */ "Connect incognito" = "Conectar incognito"; +/* No comment provided by engineer. */ +"Connect to desktop" = "Conectar con ordenador"; + /* No comment provided by engineer. */ "connect to SimpleX Chat developers." = "contacta con los desarrolladores de SimpleX Chat."; /* No comment provided by engineer. */ -"Connect via link" = "Conectar mediante enlace"; +"Connect to yourself?" = "¿Conectarte a tí mismo?"; /* No comment provided by engineer. */ -"Connect via link / QR code" = "Conecta vía enlace / Código QR"; +"Connect to yourself?\nThis is your own one-time link!" = "¿Conectarte a tí mismo?\n¡Este es tu propio enlace de un solo uso!"; + +/* No comment provided by engineer. */ +"Connect to yourself?\nThis is your own SimpleX address!" = "¿Conectarte a tí mismo?\n¡Esta es tu propia dirección SimpleX!"; + +/* No comment provided by engineer. */ +"Connect via contact address" = "Conectar mediante dirección de contacto"; + +/* No comment provided by engineer. */ +"Connect via link" = "Conectar mediante enlace"; /* No comment provided by engineer. */ "Connect via one-time link" = "Conectar mediante enlace de un sólo uso"; +/* No comment provided by engineer. */ +"Connect with %@" = "Conectar con %@"; + /* No comment provided by engineer. */ "connected" = "conectado"; +/* No comment provided by engineer. */ +"Connected desktop" = "Ordenador conectado"; + /* rcv group event chat item */ "connected directly" = "conectado directamente"; +/* No comment provided by engineer. */ +"Connected to desktop" = "Conectado con ordenador"; + /* No comment provided by engineer. */ "connecting" = "conectando"; @@ -765,6 +858,9 @@ /* No comment provided by engineer. */ "Connecting server… (error: %@)" = "Conectando con el servidor... (error: %@)"; +/* No comment provided by engineer. */ +"Connecting to desktop" = "Conectando con ordenador"; + /* chat list item title */ "connecting…" = "conectando…"; @@ -783,6 +879,9 @@ /* No comment provided by engineer. */ "Connection request sent!" = "¡Solicitud de conexión enviada!"; +/* No comment provided by engineer. */ +"Connection terminated" = "Conexión finalizada"; + /* No comment provided by engineer. */ "Connection timeout" = "Tiempo de conexión expirado"; @@ -831,15 +930,24 @@ /* No comment provided by engineer. */ "Core version: v%@" = "Versión Core: v%@"; +/* No comment provided by engineer. */ +"Correct name to %@?" = "¿Corregir el nombre a %@?"; + /* No comment provided by engineer. */ "Create" = "Crear"; +/* No comment provided by engineer. */ +"Create a group using a random profile." = "Crear grupo usando perfil aleatorio."; + /* No comment provided by engineer. */ "Create an address to let people connect with you." = "Crea una dirección para que otras personas puedan conectar contigo."; /* server test step */ "Create file" = "Crear archivo"; +/* No comment provided by engineer. */ +"Create group" = "Crear grupo"; + /* No comment provided by engineer. */ "Create group link" = "Crear enlace de grupo"; @@ -850,7 +958,7 @@ "Create new profile in [desktop app](https://simplex.chat/downloads/). 💻" = "Crea perfil nuevo en la [aplicación para PC](https://simplex.Descargas/de chat/). 💻"; /* No comment provided by engineer. */ -"Create one-time invitation link" = "Crea enlace de invitación de un uso"; +"Create profile" = "Crear perfil"; /* server test step */ "Create queue" = "Crear cola"; @@ -859,7 +967,7 @@ "Create secret group" = "Crea grupo secreto"; /* No comment provided by engineer. */ -"Create SimpleX address" = "Crear tu dirección SimpleX"; +"Create SimpleX address" = "Crear dirección SimpleX"; /* No comment provided by engineer. */ "Create your profile" = "Crea tu perfil"; @@ -867,6 +975,9 @@ /* No comment provided by engineer. */ "Created on %@" = "Creado en %@"; +/* No comment provided by engineer. */ +"Creating link…" = "Creando enlace…"; + /* No comment provided by engineer. */ "creator" = "creador"; @@ -966,6 +1077,9 @@ /* chat item action */ "Delete" = "Eliminar"; +/* No comment provided by engineer. */ +"Delete %lld messages?" = "¿Elimina %lld mensajes?"; + /* No comment provided by engineer. */ "Delete address" = "Eliminar dirección"; @@ -978,6 +1092,9 @@ /* No comment provided by engineer. */ "Delete all files" = "Eliminar todos los archivos"; +/* No comment provided by engineer. */ +"Delete and notify contact" = "Eliminar y notificar contacto"; + /* No comment provided by engineer. */ "Delete archive" = "Eliminar archivo"; @@ -999,6 +1116,9 @@ /* No comment provided by engineer. */ "Delete Contact" = "Eliminar contacto"; +/* No comment provided by engineer. */ +"Delete contact?\nThis cannot be undone!" = "¿Eliminar contacto?\n¡No podrá deshacerse!"; + /* No comment provided by engineer. */ "Delete database" = "Eliminar base de datos"; @@ -1054,7 +1174,7 @@ "Delete pending connection" = "Eliminar conexión pendiente"; /* No comment provided by engineer. */ -"Delete pending connection?" = "¿Eliminar la conexion pendiente?"; +"Delete pending connection?" = "¿Eliminar conexión pendiente?"; /* No comment provided by engineer. */ "Delete profile" = "Eliminar perfil"; @@ -1074,6 +1194,9 @@ /* copied message info */ "Deleted at: %@" = "Eliminado: %@"; +/* rcv direct event chat item */ +"deleted contact" = "contacto eliminado"; + /* rcv group event chat item */ "deleted group" = "grupo eliminado"; @@ -1089,6 +1212,15 @@ /* No comment provided by engineer. */ "Description" = "Descripción"; +/* No comment provided by engineer. */ +"Desktop address" = "Dirección ordenador"; + +/* No comment provided by engineer. */ +"Desktop app version %@ is not compatible with this app." = "La versión de aplicación del ordenador %\" no es compatible con esta aplicación."; + +/* No comment provided by engineer. */ +"Desktop devices" = "Ordenadores"; + /* No comment provided by engineer. */ "Develop" = "Desarrollo"; @@ -1152,9 +1284,15 @@ /* server test step */ "Disconnect" = "Desconectar"; +/* No comment provided by engineer. */ +"Disconnect desktop?" = "¿Desconectar ordenador?"; + /* No comment provided by engineer. */ "Discover and join groups" = "Descubre y únete a grupos"; +/* No comment provided by engineer. */ +"Discover via local network" = "Descubrir en red local"; + /* No comment provided by engineer. */ "Do it later" = "Hacer más tarde"; @@ -1203,6 +1341,9 @@ /* No comment provided by engineer. */ "Enable automatic message deletion?" = "¿Activar eliminación automática de mensajes?"; +/* No comment provided by engineer. */ +"Enable camera access" = "Permitir acceso a la cámara"; + /* No comment provided by engineer. */ "Enable for all" = "Activar para todos"; @@ -1257,6 +1398,9 @@ /* notification */ "Encrypted message or another event" = "Mensaje cifrado u otro evento"; +/* notification */ +"Encrypted message: app is stopped" = "Mensaje cifrado: la aplicación está parada"; + /* notification */ "Encrypted message: database error" = "Mensaje cifrado: error base de datos"; @@ -1290,6 +1434,12 @@ /* chat item text */ "encryption re-negotiation allowed for %@" = "renegociar el cifrado permitido para %@"; +/* message decrypt error item */ +"Encryption re-negotiation error" = "Error de renegociación de cifrado"; + +/* No comment provided by engineer. */ +"Encryption re-negotiation failed." = "Renegociación de cifrado fallida."; + /* chat item text */ "encryption re-negotiation required" = "se requiere renegociar el cifrado"; @@ -1305,6 +1455,9 @@ /* No comment provided by engineer. */ "Enter correct passphrase." = "Introduce la contraseña correcta."; +/* No comment provided by engineer. */ +"Enter group name…" = "Nombre del grupo…"; + /* No comment provided by engineer. */ "Enter Passcode" = "Introduce Código"; @@ -1317,12 +1470,18 @@ /* No comment provided by engineer. */ "Enter server manually" = "Introduce el servidor manualmente"; +/* No comment provided by engineer. */ +"Enter this device name…" = "Nombre de este dispositivo…"; + /* placeholder */ "Enter welcome message…" = "Introduce mensaje de bienvenida…"; /* placeholder */ "Enter welcome message… (optional)" = "Introduce mensaje de bienvenida… (opcional)"; +/* No comment provided by engineer. */ +"Enter your name…" = "Introduce tu nombre…"; + /* No comment provided by engineer. */ "error" = "error"; @@ -1342,7 +1501,7 @@ "Error adding member(s)" = "Error al añadir miembro(s)"; /* No comment provided by engineer. */ -"Error changing address" = "Error al cambiar dirección"; +"Error changing address" = "Error al cambiar servidor"; /* No comment provided by engineer. */ "Error changing role" = "Error al cambiar rol"; @@ -1408,11 +1567,14 @@ "Error importing chat database" = "Error al importar base de datos"; /* No comment provided by engineer. */ -"Error joining group" = "Error al unirse al grupo"; +"Error joining group" = "Error al unirte al grupo"; /* No comment provided by engineer. */ "Error loading %@ servers" = "Error al cargar servidores %@"; +/* No comment provided by engineer. */ +"Error opening chat" = "Error al abrir chat"; + /* No comment provided by engineer. */ "Error receiving file" = "Error al recibir archivo"; @@ -1437,6 +1599,9 @@ /* No comment provided by engineer. */ "Error saving user password" = "Error al guardar contraseña de usuario"; +/* No comment provided by engineer. */ +"Error scanning code: %@" = "Error al escanear código: %@"; + /* No comment provided by engineer. */ "Error sending email" = "Error al enviar email"; @@ -1494,6 +1659,9 @@ /* No comment provided by engineer. */ "Exit without saving" = "Salir sin guardar"; +/* chat item action */ +"Expand" = "Expandir"; + /* No comment provided by engineer. */ "Export database" = "Exportar base de datos"; @@ -1512,6 +1680,9 @@ /* No comment provided by engineer. */ "Fast and no wait until the sender is online!" = "¡Rápido y sin necesidad de esperar a que el remitente esté en línea!"; +/* No comment provided by engineer. */ +"Faster joining and more reliable messages." = "Mensajería más segura y conexión más rápida."; + /* No comment provided by engineer. */ "Favorite" = "Favoritos"; @@ -1569,6 +1740,9 @@ /* No comment provided by engineer. */ "For console" = "Para consola"; +/* No comment provided by engineer. */ +"Found desktop" = "Ordenador encontrado"; + /* No comment provided by engineer. */ "French interface" = "Interfaz en francés"; @@ -1581,6 +1755,9 @@ /* No comment provided by engineer. */ "Full name:" = "Nombre completo:"; +/* No comment provided by engineer. */ +"Fully decentralized – visible only to members." = "Completamente descentralizado: sólo visible a los miembros."; + /* No comment provided by engineer. */ "Fully re-implemented - work in background!" = "Completamente reimplementado: ¡funciona en segundo plano!"; @@ -1593,6 +1770,12 @@ /* No comment provided by engineer. */ "Group" = "Grupo"; +/* No comment provided by engineer. */ +"Group already exists" = "El grupo ya existe"; + +/* No comment provided by engineer. */ +"Group already exists!" = "¡El grupo ya existe!"; + /* No comment provided by engineer. */ "group deleted" = "grupo eliminado"; @@ -1624,7 +1807,7 @@ "Group members can add message reactions." = "Los miembros pueden añadir reacciones a los mensajes."; /* No comment provided by engineer. */ -"Group members can irreversibly delete sent messages." = "Los miembros del grupo pueden eliminar mensajes de forma irreversible."; +"Group members can irreversibly delete sent messages. (24 hours)" = "Los miembros del grupo pueden eliminar mensajes de forma irreversible. (24 horas)"; /* No comment provided by engineer. */ "Group members can send direct messages." = "Los miembros del grupo pueden enviar mensajes directos."; @@ -1645,7 +1828,7 @@ "Group moderation" = "Moderación de grupos"; /* No comment provided by engineer. */ -"Group preferences" = "Preferencias de grupo"; +"Group preferences" = "Preferencias del grupo"; /* No comment provided by engineer. */ "Group profile" = "Perfil de grupo"; @@ -1716,9 +1899,6 @@ /* No comment provided by engineer. */ "If you can't meet in person, show QR code in a video call, or share the link." = "Si no puedes reunirte en persona, muestra el código QR por videollamada, o comparte el enlace."; -/* No comment provided by engineer. */ -"If you cannot meet in person, you can **scan QR code in the video call**, or your contact can share an invitation link." = "Si no puedes reunirte en persona, puedes **escanear el código QR por videollamada**, o tu contacto puede compartir un enlace de invitación."; - /* No comment provided by engineer. */ "If you enter this passcode when opening the app, all app data will be irreversibly removed!" = "¡Si introduces este código al abrir la aplicación, todos los datos de la misma se eliminarán de forma irreversible!"; @@ -1764,6 +1944,9 @@ /* No comment provided by engineer. */ "Incognito" = "Incógnito"; +/* No comment provided by engineer. */ +"Incognito groups" = "Grupos incógnito"; + /* No comment provided by engineer. */ "Incognito mode" = "Modo incógnito"; @@ -1791,6 +1974,9 @@ /* No comment provided by engineer. */ "Incompatible database version" = "Versión de base de datos incompatible"; +/* No comment provided by engineer. */ +"Incompatible version" = "Versión incompatible"; + /* PIN entry */ "Incorrect passcode" = "Código de acceso incorrecto"; @@ -1830,6 +2016,18 @@ /* invalid chat item */ "invalid data" = "datos no válidos"; +/* No comment provided by engineer. */ +"Invalid link" = "Enlace no válido"; + +/* No comment provided by engineer. */ +"Invalid name!" = "¡Nombre no válido!"; + +/* No comment provided by engineer. */ +"Invalid QR code" = "Código QR no válido"; + +/* No comment provided by engineer. */ +"Invalid response" = "Respuesta no válida"; + /* No comment provided by engineer. */ "Invalid server address!" = "¡Dirección de servidor no válida!"; @@ -1858,7 +2056,7 @@ "invited %@" = "ha invitado a %@"; /* chat list item title */ -"invited to connect" = "invitado a conectarse"; +"invited to connect" = "invitación a conectarse"; /* rcv group event chat item */ "invited via your group link" = "se ha unido mediante tu enlace de grupo"; @@ -1900,20 +2098,38 @@ "Japanese interface" = "Interfáz en japonés"; /* No comment provided by engineer. */ -"Join" = "Únete"; +"Join" = "Unirte"; /* No comment provided by engineer. */ "join as %@" = "unirte como %@"; /* No comment provided by engineer. */ -"Join group" = "Únete al grupo"; +"Join group" = "Unirte al grupo"; /* No comment provided by engineer. */ -"Join incognito" = "Únete en modo incógnito"; +"Join group?" = "¿Unirte al grupo?"; + +/* No comment provided by engineer. */ +"Join incognito" = "Unirte en modo incógnito"; + +/* No comment provided by engineer. */ +"Join with current profile" = "Unirte con el perfil actual"; + +/* No comment provided by engineer. */ +"Join your group?\nThis is your link for group %@!" = "¿Unirse a tu grupo?\n¡Este es tu enlace para el grupo %@!"; /* No comment provided by engineer. */ "Joining group" = "Entrando al grupo"; +/* No comment provided by engineer. */ +"Keep" = "Guardar"; + +/* No comment provided by engineer. */ +"Keep the app open to use it from desktop" = "Mantén la aplicación abierta para usarla desde el ordenador"; + +/* No comment provided by engineer. */ +"Keep unused invitation?" = "¿Guardar invitación no usada?"; + /* No comment provided by engineer. */ "Keep your connections" = "Conserva tus conexiones"; @@ -1950,6 +2166,15 @@ /* No comment provided by engineer. */ "Limitations" = "Limitaciones"; +/* No comment provided by engineer. */ +"Link mobile and desktop apps! 🔗" = "¡Enlazar aplicación móvil con ordenador! 🔗"; + +/* No comment provided by engineer. */ +"Linked desktop options" = "Opciones ordenador enlazado"; + +/* No comment provided by engineer. */ +"Linked desktops" = "Ordenadores enlazados"; + /* No comment provided by engineer. */ "LIVE" = "EN VIVO"; @@ -1959,6 +2184,9 @@ /* No comment provided by engineer. */ "Live messages" = "Mensajes en vivo"; +/* No comment provided by engineer. */ +"Local" = "Local"; + /* No comment provided by engineer. */ "Local name" = "Nombre local"; @@ -2017,10 +2245,10 @@ "member connected" = "conectado"; /* No comment provided by engineer. */ -"Member role will be changed to \"%@\". All group members will be notified." = "El rol de miembro cambiará a \"%@\". Todos los miembros del grupo serán notificados."; +"Member role will be changed to \"%@\". All group members will be notified." = "El rol del miembro cambiará a \"%@\" y se notificará al grupo."; /* No comment provided by engineer. */ -"Member role will be changed to \"%@\". The member will receive a new invitation." = "El rol del miembro cambiará a \"%@\". El miembro recibirá una invitación nueva."; +"Member role will be changed to \"%@\". The member will receive a new invitation." = "El rol del miembro cambiará a \"%@\" y recibirá una invitación nueva."; /* No comment provided by engineer. */ "Member will be removed from group - this cannot be undone!" = "El miembro será expulsado del grupo. ¡No podrá deshacerse!"; @@ -2035,7 +2263,7 @@ "Message draft" = "Borrador de mensaje"; /* chat feature */ -"Message reactions" = "Reacciones a los mensajes"; +"Message reactions" = "Reacciones a mensajes"; /* No comment provided by engineer. */ "Message reactions are prohibited in this chat." = "Las reacciones a los mensajes no están permitidas en este chat."; @@ -2055,6 +2283,9 @@ /* No comment provided by engineer. */ "Messages & files" = "Mensajes"; +/* No comment provided by engineer. */ +"Messages from %@ will be shown!" = "¡Los mensajes de %@ serán mostrados!"; + /* No comment provided by engineer. */ "Migrating database archive…" = "Migrando base de datos…"; @@ -2127,6 +2358,9 @@ /* No comment provided by engineer. */ "never" = "nunca"; +/* No comment provided by engineer. */ +"New chat" = "Nuevo chat"; + /* notification */ "New contact request" = "Nueva solicitud de contacto"; @@ -2202,6 +2436,9 @@ /* copied message info in history */ "no text" = "sin texto"; +/* No comment provided by engineer. */ +"Not compatible!" = "¡No compatible!"; + /* No comment provided by engineer. */ "Notifications" = "Notificaciones"; @@ -2222,9 +2459,6 @@ /* No comment provided by engineer. */ "Off" = "Desactivado"; -/* No comment provided by engineer. */ -"Off (Local)" = "Desactivado (Local)"; - /* feature offered item */ "offered %@" = "ofrecido %@"; @@ -2234,6 +2468,9 @@ /* No comment provided by engineer. */ "Ok" = "Ok"; +/* No comment provided by engineer. */ +"OK" = "OK"; + /* No comment provided by engineer. */ "Old database" = "Base de datos antigua"; @@ -2259,7 +2496,7 @@ "Only client devices store user profiles, contacts, groups, and messages sent with **2-layer end-to-end encryption**." = "Sólo los dispositivos cliente almacenan perfiles de usuario, contactos, grupos y mensajes enviados con **cifrado de extremo a extremo de 2 capas**."; /* No comment provided by engineer. */ -"Only group owners can change group preferences." = "Sólo los propietarios pueden modificar las preferencias de grupo."; +"Only group owners can change group preferences." = "Sólo los propietarios pueden modificar las preferencias del grupo."; /* No comment provided by engineer. */ "Only group owners can enable files and media." = "Sólo los propietarios del grupo pueden activar los archivos y multimedia."; @@ -2271,7 +2508,7 @@ "Only you can add message reactions." = "Sólo tú puedes añadir reacciones a los mensajes."; /* No comment provided by engineer. */ -"Only you can irreversibly delete messages (your contact can mark them for deletion)." = "Sólo tú puedes eliminar mensajes de forma irreversible (tu contacto puede marcarlos para eliminar)."; +"Only you can irreversibly delete messages (your contact can mark them for deletion). (24 hours)" = "Sólo tú puedes eliminar mensajes de forma irreversible (tu contacto puede marcarlos para eliminar). (24 horas)"; /* No comment provided by engineer. */ "Only you can make calls." = "Solo tú puedes realizar llamadas."; @@ -2286,7 +2523,7 @@ "Only your contact can add message reactions." = "Sólo tu contacto puede añadir reacciones a los mensajes."; /* No comment provided by engineer. */ -"Only your contact can irreversibly delete messages (you can mark them for deletion)." = "Sólo tu contacto puede eliminar mensajes de forma irreversible (tu puedes marcarlos para eliminar)."; +"Only your contact can irreversibly delete messages (you can mark them for deletion). (24 hours)" = "Sólo tu contacto puede eliminar mensajes de forma irreversible (tu puedes marcarlos para eliminar). (24 horas)"; /* No comment provided by engineer. */ "Only your contact can make calls." = "Sólo tu contacto puede realizar llamadas."; @@ -2306,6 +2543,9 @@ /* authentication reason */ "Open chat console" = "Abrir consola de Chat"; +/* No comment provided by engineer. */ +"Open group" = "Grupo abierto"; + /* No comment provided by engineer. */ "Open Settings" = "Abrir Configuración"; @@ -2316,7 +2556,13 @@ "Open-source protocol and code – anybody can run the servers." = "Protocolo y código abiertos: cualquiera puede usar los servidores."; /* No comment provided by engineer. */ -"Opening database…" = "Abriendo base de datos…"; +"Opening app…" = "Iniciando aplicación…"; + +/* No comment provided by engineer. */ +"Or scan QR code" = "O escanear código QR"; + +/* No comment provided by engineer. */ +"Or show this code" = "O mostrar este código"; /* member role */ "owner" = "propietario"; @@ -2340,16 +2586,13 @@ "Password to show" = "Contraseña para hacerlo visible"; /* No comment provided by engineer. */ -"Paste" = "Pegar"; +"Paste desktop address" = "Pegar dirección de ordenador"; /* No comment provided by engineer. */ "Paste image" = "Pegar imagen"; /* No comment provided by engineer. */ -"Paste received link" = "Pegar enlace recibido"; - -/* placeholder */ -"Paste the link you received to connect with your contact." = "Pega el enlace que has recibido en el recuadro para conectar con tu contacto."; +"Paste the link you received" = "Pegar el enlace recibido"; /* No comment provided by engineer. */ "peer-to-peer" = "p2p"; @@ -2382,7 +2625,10 @@ "Please check yours and your contact preferences." = "Comprueba tus preferencias y las de tu contacto."; /* No comment provided by engineer. */ -"Please contact group admin." = "Póngase en contacto con el administrador del grupo."; +"Please contact developers.\nError: %@" = "Por favor, contacta con los desarrolladores.\nError: %@"; + +/* No comment provided by engineer. */ +"Please contact group admin." = "Ponte en contacto con el administrador del grupo."; /* No comment provided by engineer. */ "Please enter correct current passphrase." = "Introduce la contraseña actual correcta."; @@ -2438,6 +2684,12 @@ /* No comment provided by engineer. */ "Profile image" = "Imagen del perfil"; +/* No comment provided by engineer. */ +"Profile name" = "Nombre del perfil"; + +/* No comment provided by engineer. */ +"Profile name:" = "Nombre del perfil:"; + /* No comment provided by engineer. */ "Profile password" = "Contraseña del perfil"; @@ -2496,16 +2748,19 @@ "Read more" = "Saber más"; /* No comment provided by engineer. */ -"Read more in [User Guide](https://simplex.chat/docs/guide/app-settings.html#your-simplex-contact-address)." = "Más información en el [Manual de usuario](https://simplex.chat/docs/guide/app-settings.html#your-simplex-contact-address)."; +"Read more in [User Guide](https://simplex.chat/docs/guide/app-settings.html#your-simplex-contact-address)." = "Saber más en el [Manual del Usuario](https://simplex.chat/docs/guide/app-settings.html#your-simplex-contact-address)."; /* No comment provided by engineer. */ -"Read more in [User Guide](https://simplex.chat/docs/guide/readme.html#connect-to-friends)." = "Más información en el [Manual de usuario](https://simplex.chat/docs/guide/readme.html#connect-to-friends)."; +"Read more in [User Guide](https://simplex.chat/docs/guide/chat-profiles.html#incognito-mode)." = "Saber más en [Guía de Usuario](https://simplex.chat/docs/guide/chat-profiles.html#incognito-mode)."; /* No comment provided by engineer. */ -"Read more in our [GitHub repository](https://github.com/simplex-chat/simplex-chat#readme)." = "Más información en nuestro [repositorio GitHub](https://github.com/simplex-chat/simplex-chat#readme)."; +"Read more in [User Guide](https://simplex.chat/docs/guide/readme.html#connect-to-friends)." = "Saber más en el [Manual del Usuario](https://simplex.chat/docs/guide/readme.html#connect-to-friends)."; /* No comment provided by engineer. */ -"Read more in our GitHub repository." = "Más información en nuestro repositorio GitHub."; +"Read more in our [GitHub repository](https://github.com/simplex-chat/simplex-chat#readme)." = "Saber más en nuestro [repositorio GitHub](https://github.com/simplex-chat/simplex-chat#readme)."; + +/* No comment provided by engineer. */ +"Read more in our GitHub repository." = "Saber más en nuestro repositorio GitHub."; /* No comment provided by engineer. */ "Receipts are disabled" = "Las confirmaciones están desactivadas"; @@ -2603,6 +2858,12 @@ /* No comment provided by engineer. */ "Renegotiate encryption?" = "¿Renegociar cifrado?"; +/* No comment provided by engineer. */ +"Repeat connection request?" = "¿Repetir solicitud de conexión?"; + +/* No comment provided by engineer. */ +"Repeat join request?" = "¿Repetir solicitud de admisión?"; + /* chat item action */ "Reply" = "Responder"; @@ -2636,6 +2897,9 @@ /* No comment provided by engineer. */ "Restore database error" = "Error al restaurar base de datos"; +/* No comment provided by engineer. */ +"Retry" = "Reintentar"; + /* chat item action */ "Reveal" = "Revelar"; @@ -2667,10 +2931,10 @@ "Save and notify contact" = "Guardar y notificar contacto"; /* No comment provided by engineer. */ -"Save and notify group members" = "Guardar y notificar a los miembros del grupo"; +"Save and notify group members" = "Guardar y notificar grupo"; /* No comment provided by engineer. */ -"Save and update group profile" = "Guardar y actualizar perfil de grupo"; +"Save and update group profile" = "Guardar y actualizar perfil del grupo"; /* No comment provided by engineer. */ "Save archive" = "Guardar archivo"; @@ -2714,6 +2978,9 @@ /* No comment provided by engineer. */ "Scan QR code" = "Escanear código QR"; +/* No comment provided by engineer. */ +"Scan QR code from desktop" = "Escanear código QR desde ordenador"; + /* No comment provided by engineer. */ "Scan security code from your contact's app." = "Escanea el código de seguridad desde la aplicación de tu contacto."; @@ -2723,6 +2990,9 @@ /* No comment provided by engineer. */ "Search" = "Buscar"; +/* No comment provided by engineer. */ +"Search or paste SimpleX link" = "Buscar o pegar enlace SimpleX"; + /* network option */ "sec" = "seg"; @@ -2858,6 +3128,9 @@ /* No comment provided by engineer. */ "Servers" = "Servidores"; +/* No comment provided by engineer. */ +"Session code" = "Código de sesión"; + /* No comment provided by engineer. */ "Set 1 day" = "Establecer 1 día"; @@ -2901,7 +3174,7 @@ "Share link" = "Compartir enlace"; /* No comment provided by engineer. */ -"Share one-time invitation link" = "Compartir enlace de invitación de un uso"; +"Share this 1-time invite link" = "Compartir este enlace de un uso"; /* No comment provided by engineer. */ "Share with contacts" = "Compartir con contactos"; @@ -2979,10 +3252,10 @@ "Somebody" = "Alguien"; /* No comment provided by engineer. */ -"Start a new chat" = "Iniciar chat nuevo"; +"Start chat" = "Iniciar chat"; /* No comment provided by engineer. */ -"Start chat" = "Iniciar chat"; +"Start chat?" = "¿Iniciar chat?"; /* No comment provided by engineer. */ "Start migration" = "Iniciar migración"; @@ -3045,11 +3318,20 @@ "Tap to activate profile." = "Pulsa sobre un perfil para activarlo."; /* No comment provided by engineer. */ -"Tap to join" = "Pulsa para unirse"; +"Tap to Connect" = "Pulsa para conectar"; + +/* No comment provided by engineer. */ +"Tap to join" = "Pulsa para unirte"; /* No comment provided by engineer. */ "Tap to join incognito" = "Pulsa para unirte en modo incógnito"; +/* No comment provided by engineer. */ +"Tap to paste link" = "Pulsa para pegar enlace"; + +/* No comment provided by engineer. */ +"Tap to scan" = "Pulsa para escanear"; + /* No comment provided by engineer. */ "Tap to start a new chat" = "Pulsa para iniciar chat nuevo"; @@ -3095,6 +3377,9 @@ /* No comment provided by engineer. */ "The attempt to change database passphrase was not completed." = "El intento de cambiar la contraseña de la base de datos no se ha completado."; +/* No comment provided by engineer. */ +"The code you scanned is not a SimpleX link QR code." = "El código QR escaneado no es un enlace SimpleX."; + /* No comment provided by engineer. */ "The connection you accepted will be cancelled!" = "¡La conexión que has aceptado se cancelará!"; @@ -3137,15 +3422,12 @@ /* No comment provided by engineer. */ "The servers for new connections of your current chat profile **%@**." = "Lista de servidores para las conexiones nuevas de tu perfil actual **%@**."; +/* No comment provided by engineer. */ +"The text you pasted is not a SimpleX link." = "El texto pegado no es un enlace SimpleX."; + /* No comment provided by engineer. */ "Theme" = "Tema"; -/* No comment provided by engineer. */ -"There should be at least one user profile." = "Debe haber al menos un perfil."; - -/* No comment provided by engineer. */ -"There should be at least one visible user profile." = "Debe haber al menos un perfil visible."; - /* No comment provided by engineer. */ "These settings are for your current profile **%@**." = "Esta configuración afecta a tu perfil actual **%@**."; @@ -3164,12 +3446,21 @@ /* notification title */ "this contact" = "este contacto"; +/* No comment provided by engineer. */ +"This device name" = "Nombre del dispositivo"; + /* No comment provided by engineer. */ "This group has over %lld members, delivery receipts are not sent." = "Este grupo tiene más de %lld miembros, no se enviarán confirmaciones de entrega."; /* No comment provided by engineer. */ "This group no longer exists." = "Este grupo ya no existe."; +/* No comment provided by engineer. */ +"This is your own one-time link!" = "¡Este es tu propio enlace de un solo uso!"; + +/* No comment provided by engineer. */ +"This is your own SimpleX address!" = "¡Esta es tu propia dirección SimpleX!"; + /* No comment provided by engineer. */ "This setting applies to messages in your current chat profile **%@**." = "Esta configuración se aplica a los mensajes del perfil actual **%@**."; @@ -3179,17 +3470,20 @@ /* No comment provided by engineer. */ "To connect, your contact can scan QR code or use the link in the app." = "Para conectarse, tu contacto puede escanear el código QR o usar el enlace en la aplicación."; +/* No comment provided by engineer. */ +"To hide unwanted messages." = "Para ocultar mensajes no deseados."; + /* No comment provided by engineer. */ "To make a new connection" = "Para hacer una conexión nueva"; /* No comment provided by engineer. */ -"To protect privacy, instead of user IDs used by all other platforms, SimpleX has identifiers for message queues, separate for each of your contacts." = "Para proteger la privacidad, en lugar de los identificadores de usuario que usan el resto de plataformas, SimpleX dispone de identificadores para las colas de mensajes, independientes para cada uno de tus contactos."; +"To protect privacy, instead of user IDs used by all other platforms, SimpleX has identifiers for message queues, separate for each of your contacts." = "Para proteger tu privacidad, en lugar de los identificadores de usuario que usan el resto de plataformas, SimpleX dispone de identificadores para las colas de mensajes, independientes para cada uno de tus contactos."; /* No comment provided by engineer. */ "To protect timezone, image/voice files use UTC." = "Para proteger la zona horaria, los archivos de imagen/voz usan la hora UTC."; /* No comment provided by engineer. */ -"To protect your information, turn on SimpleX Lock.\nYou will be prompted to complete authentication before this feature is enabled." = "Para proteger tu información, activa Bloqueo SimpleX.\nSe te pedirá que completes la autenticación antes de activar esta función."; +"To protect your information, turn on SimpleX Lock.\nYou will be prompted to complete authentication before this feature is enabled." = "Para proteger tu información, activa el Bloqueo SimpleX.\nSe te pedirá que completes la autenticación antes de activar esta función."; /* 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."; @@ -3201,7 +3495,7 @@ "To support instant push notifications the chat database has to be migrated." = "Para permitir las notificaciones automáticas instantáneas, la base de datos se debe migrar."; /* No comment provided by engineer. */ -"To verify end-to-end encryption with your contact compare (or scan) the code on your devices." = "Para comprobar el cifrado de extremo a extremo con tu contacto compara (o escanea) el código en tus dispositivos."; +"To verify end-to-end encryption with your contact compare (or scan) the code on your devices." = "Para verificar el cifrado de extremo a extremo con tu contacto, compara (o escanea) el código en ambos dispositivos."; /* No comment provided by engineer. */ "Toggle incognito when connecting." = "Activa incógnito al conectar."; @@ -3218,15 +3512,21 @@ /* No comment provided by engineer. */ "Turn off" = "Desactivar"; -/* No comment provided by engineer. */ -"Turn off notifications?" = "¿Desactivar notificaciones?"; - /* No comment provided by engineer. */ "Turn on" = "Activar"; /* No comment provided by engineer. */ "Unable to record voice message" = "No se puede grabar mensaje de voz"; +/* No comment provided by engineer. */ +"Unblock" = "Desbloquear"; + +/* No comment provided by engineer. */ +"Unblock member" = "Desbloquear miembro"; + +/* No comment provided by engineer. */ +"Unblock member?" = "¿Desbloquear miembro?"; + /* item status description */ "Unexpected error: %@" = "Error inesperado: %@"; @@ -3266,6 +3566,12 @@ /* No comment provided by engineer. */ "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." = "A menos que tu contacto haya eliminado la conexión o\nque este enlace ya se haya usado, podría ser un error. Por favor, notifícalo.\nPara conectarte, pide a tu contacto que cree otro enlace de conexión y comprueba que tienes buena conexión de red."; +/* No comment provided by engineer. */ +"Unlink" = "Desenlazar"; + +/* No comment provided by engineer. */ +"Unlink desktop?" = "¿Desenlazar ordenador?"; + /* No comment provided by engineer. */ "Unlock" = "Desbloquear"; @@ -3320,12 +3626,18 @@ /* No comment provided by engineer. */ "Use for new connections" = "Usar para conexiones nuevas"; +/* No comment provided by engineer. */ +"Use from desktop" = "Usar desde ordenador"; + /* No comment provided by engineer. */ "Use iOS call interface" = "Usar interfaz de llamada de iOS"; /* No comment provided by engineer. */ "Use new incognito profile" = "Usar nuevo perfil incógnito"; +/* No comment provided by engineer. */ +"Use only local notifications?" = "¿Usar sólo notificaciones locales?"; + /* No comment provided by engineer. */ "Use server" = "Usar servidor"; @@ -3341,12 +3653,24 @@ /* No comment provided by engineer. */ "Using SimpleX Chat servers." = "Usar servidores SimpleX Chat."; +/* No comment provided by engineer. */ +"v%@" = "v%@"; + /* No comment provided by engineer. */ "v%@ (%@)" = "v%@ (%@)"; +/* No comment provided by engineer. */ +"Verify code with desktop" = "Verificar código con ordenador"; + +/* No comment provided by engineer. */ +"Verify connection" = "Verificar conexión"; + /* No comment provided by engineer. */ "Verify connection security" = "Comprobar la seguridad de la conexión"; +/* No comment provided by engineer. */ +"Verify connections" = "Verificar conexiones"; + /* No comment provided by engineer. */ "Verify security code" = "Comprobar código de seguridad"; @@ -3365,6 +3689,9 @@ /* No comment provided by engineer. */ "via relay" = "mediante retransmisor"; +/* No comment provided by engineer. */ +"Via secure quantum resistant protocol." = "Mediante protocolo seguro de resistencia cuántica."; + /* No comment provided by engineer. */ "Video call" = "Videollamada"; @@ -3404,6 +3731,9 @@ /* No comment provided by engineer. */ "waiting for confirmation…" = "esperando confirmación…"; +/* No comment provided by engineer. */ +"Waiting for desktop..." = "Esperando ordenador..."; + /* No comment provided by engineer. */ "Waiting for file" = "Esperando archivo"; @@ -3473,14 +3803,35 @@ /* No comment provided by engineer. */ "You are already connected to %@." = "Ya estás conectado a %@."; +/* No comment provided by engineer. */ +"You are already connecting to %@." = "Ya estás conectando con %@."; + +/* No comment provided by engineer. */ +"You are already connecting via this one-time link!" = "¡Ya estás conectando mediante este enlace de un solo uso!"; + +/* No comment provided by engineer. */ +"You are already in group %@." = "Ya estás en el grupo %@."; + +/* No comment provided by engineer. */ +"You are already joining the group %@." = "Ya estás uniéndote al grupo %@."; + +/* No comment provided by engineer. */ +"You are already joining the group via this link!" = "¡Ya estás uniéndote al grupo mediante este enlace!"; + +/* No comment provided by engineer. */ +"You are already joining the group via this link." = "Ya estás uniéndote al grupo mediante este enlace."; + +/* No comment provided by engineer. */ +"You are already joining the group!\nRepeat join request?" = "¡En proceso de unirte al grupo!\n¿Repetir solicitud de admisión?"; + /* No comment provided by engineer. */ "You are connected to the server used to receive messages from this contact." = "Estás conectado al servidor usado para recibir mensajes de este contacto."; /* No comment provided by engineer. */ -"you are invited to group" = "has sido invitado al grupo"; +"you are invited to group" = "has sido invitado a un grupo"; /* No comment provided by engineer. */ -"You are invited to group" = "Has sido invitado al grupo"; +"You are invited to group" = "Has sido invitado a un grupo"; /* No comment provided by engineer. */ "you are observer" = "Tu rol es observador"; @@ -3488,9 +3839,6 @@ /* No comment provided by engineer. */ "You can accept calls from lock screen, without device and app authentication." = "Puede aceptar llamadas desde la pantalla de bloqueo, sin autenticación de dispositivos y aplicaciones."; -/* No comment provided by engineer. */ -"You can also connect by clicking the link. If it opens in the browser, click **Open in mobile app** button." = "También puedes conectarte haciendo clic en el enlace. Si se abre en el navegador, haz clic en el botón **Abrir en aplicación móvil**."; - /* No comment provided by engineer. */ "You can create it later" = "Puedes crearla más tarde"; @@ -3503,6 +3851,9 @@ /* No comment provided by engineer. */ "You can hide or mute a user profile - swipe it to the right." = "Puedes ocultar o silenciar un perfil deslizándolo a la derecha."; +/* No comment provided by engineer. */ +"You can make it visible to your SimpleX contacts via Settings." = "Puedes hacerlo visible para tus contactos de SimpleX en Configuración."; + /* notification body */ "You can now send messages to %@" = "Ya puedes enviar mensajes a %@"; @@ -3510,13 +3861,13 @@ "You can set lock screen notification preview via settings." = "Puedes configurar las notificaciones de la pantalla de bloqueo desde Configuración."; /* No comment provided by engineer. */ -"You can share a link or a QR code - anybody will be able to join the group. You won't lose members of the group if you later delete it." = "Puedes compartir un enlace o un código QR: cualquiera podrá unirse al grupo. Si lo eliminas más tarde los miembros del grupo no se perderán."; +"You can share a link or a QR code - anybody will be able to join the group. You won't lose members of the group if you later delete it." = "Puedes compartir un enlace o código QR para que cualquiera pueda unirse al grupo. Si decides eliminarlo más tarde, los miembros del grupo se mantendrán."; /* No comment provided by engineer. */ "You can share this address with your contacts to let them connect with **%@**." = "Puedes compartir esta dirección con tus contactos para que puedan conectar con **%@**."; /* No comment provided by engineer. */ -"You can share your address as a link or QR code - anybody can connect to you." = "Puedes compartir tu dirección como enlace o como código QR: cualquiera podrá conectarse contigo."; +"You can share your address as a link or QR code - anybody can connect to you." = "Puedes compartir tu dirección como enlace o código QR para que cualquiera pueda conectarse contigo."; /* No comment provided by engineer. */ "You can start chat via app Settings / Database or by restarting the app" = "Puede iniciar Chat a través de la Configuración / Base de datos de la aplicación o reiniciando la aplicación"; @@ -3527,6 +3878,9 @@ /* No comment provided by engineer. */ "You can use markdown to format messages:" = "Puedes usar la sintaxis markdown para dar formato a tus mensajes:"; +/* No comment provided by engineer. */ +"You can view invitation link again in connection details." = "Podrás ver el enlace de invitación en detalles de conexión."; + /* No comment provided by engineer. */ "You can't send messages!" = "¡No puedes enviar mensajes!"; @@ -3548,6 +3902,12 @@ /* No comment provided by engineer. */ "You could not be verified; please try again." = "No has podido ser autenticado. Inténtalo de nuevo."; +/* No comment provided by engineer. */ +"You have already requested connection via this address!" = "¡Ya has solicitado la conexión mediante esta dirección!"; + +/* No comment provided by engineer. */ +"You have already requested connection!\nRepeat connection request?" = "Ya has solicitado la conexión\n¿Repetir solicitud?"; + /* No comment provided by engineer. */ "You have no chats" = "No tienes chats"; @@ -3582,7 +3942,7 @@ "You sent group invitation" = "Has enviado una invitación de grupo"; /* chat list item description */ -"you shared one-time link" = "has compartido un enlace de un uso"; +"you shared one-time link" = "enlace de un solo uso"; /* chat list item description */ "you shared one-time link incognito" = "has compartido enlace de un solo uso en modo incógnito"; @@ -3590,6 +3950,9 @@ /* No comment provided by engineer. */ "You will be connected to group when the group host's device is online, please wait or check later!" = "Te conectarás al grupo cuando el dispositivo del anfitrión esté en línea, por favor espera o compruébalo más tarde."; +/* No comment provided by engineer. */ +"You will be connected when group link host's device is online, please wait or check later!" = "Te conectarás cuando el dispositivo propietario del grupo esté en línea, por favor espera o compruébalo más tarde."; + /* No comment provided by engineer. */ "You will be connected when your connection request is accepted, please wait or check later!" = "Te conectarás cuando tu solicitud se acepte, por favor espera o compruébalo más tarde."; @@ -3599,6 +3962,9 @@ /* No comment provided by engineer. */ "You will be required to authenticate when you start or resume the app after 30 seconds in background." = "Se te pedirá identificarte cuándo inicies o continues usando la aplicación tras 30 segundos en segundo plano."; +/* No comment provided by engineer. */ +"You will connect to all group members." = "Te conectarás con todos los miembros del grupo."; + /* No comment provided by engineer. */ "You will still receive calls and notifications from muted profiles when they are active." = "Seguirás recibiendo llamadas y notificaciones de los perfiles silenciados cuando estén activos."; @@ -3615,7 +3981,7 @@ "You're trying to invite contact with whom you've shared an incognito profile to the group in which you're using your main profile" = "Estás intentando invitar a un contacto con el que compartes un perfil incógnito a un grupo en el que usas tu perfil principal"; /* No comment provided by engineer. */ -"You're using an incognito profile for this group - to prevent sharing your main profile inviting contacts is not allowed" = "Estás usando un perfil incógnito para este grupo, por tanto para evitar compartir tu perfil principal no se permite invitar a contactos"; +"You're using an incognito profile for this group - to prevent sharing your main profile inviting contacts is not allowed" = "Estás usando un perfil incógnito en este grupo. Para evitar descubrir tu perfil principal no se permite invitar contactos"; /* No comment provided by engineer. */ "Your %@ servers" = "Mis servidores %@"; @@ -3641,9 +4007,6 @@ /* No comment provided by engineer. */ "Your contacts can allow full message deletion." = "Tus contactos pueden permitir la eliminación completa de mensajes."; -/* No comment provided by engineer. */ -"Your contacts in SimpleX will see it.\nYou can change it in Settings." = "Tus contactos en SimpleX lo verán.\nPuedes cambiarlo en Configuración."; - /* No comment provided by engineer. */ "Your contacts will remain connected." = "Tus contactos permanecerán conectados."; @@ -3662,6 +4025,9 @@ /* No comment provided by engineer. */ "Your privacy" = "Privacidad"; +/* No comment provided by engineer. */ +"Your profile" = "Tu perfil"; + /* No comment provided by engineer. */ "Your profile **%@** will be shared." = "Tu perfil **%@** será compartido."; diff --git a/apps/ios/es.lproj/SimpleX--iOS--InfoPlist.strings b/apps/ios/es.lproj/SimpleX--iOS--InfoPlist.strings index b2dad8adaf..3fc7b2c453 100644 --- a/apps/ios/es.lproj/SimpleX--iOS--InfoPlist.strings +++ b/apps/ios/es.lproj/SimpleX--iOS--InfoPlist.strings @@ -7,6 +7,9 @@ /* Privacy - Face ID Usage Description */ "NSFaceIDUsageDescription" = "SimpleX usa reconocimiento facial para la autenticación local"; +/* Privacy - Local Network Usage Description */ +"NSLocalNetworkUsageDescription" = "SimpleX utiliza el acceso a la red local para abrir el perfil de chat en la aplicación de ordenador en la misma red."; + /* Privacy - Microphone Usage Description */ "NSMicrophoneUsageDescription" = "SimpleX necesita acceso al micrófono para las llamadas de audio, vídeo y para grabar mensajes de voz."; diff --git a/apps/ios/fi.lproj/Localizable.strings b/apps/ios/fi.lproj/Localizable.strings index fad3a54b8b..2478658ace 100644 --- a/apps/ios/fi.lproj/Localizable.strings +++ b/apps/ios/fi.lproj/Localizable.strings @@ -55,9 +55,6 @@ /* No comment provided by engineer. */ "**Add new contact**: to create your one-time QR Code for your contact." = "**Lisää uusi kontakti**: luo kertakäyttöinen QR-koodi tai linkki kontaktille."; -/* No comment provided by engineer. */ -"**Create link / QR code** for your contact to use." = "**Luo linkki / QR-koodi* kontaktille."; - /* No comment provided by engineer. */ "**e2e encrypted** audio call" = "**e2e-salattu** äänipuhelu"; @@ -70,18 +67,12 @@ /* No comment provided by engineer. */ "**Most private**: do not use SimpleX Chat notifications server, check messages periodically in the background (depends on how often you use the app)." = "**Yksityisin**: älä käytä SimpleX Chat -ilmoituspalvelinta, tarkista viestit ajoittain taustalla (riippuu siitä, kuinka usein käytät sovellusta)."; -/* No comment provided by engineer. */ -"**Paste received link** or open it in the browser and tap **Open in mobile app**." = "**Liitä vastaanotettu linkki** tai avaa se selaimessa ja napauta **Avaa mobiilisovelluksessa**."; - /* No comment provided by engineer. */ "**Please note**: you will NOT be able to recover or change passphrase if you lose it." = "**Huomaa**: et voi palauttaa tai muuttaa tunnuslausetta, jos kadotat sen."; /* No comment provided by engineer. */ "**Recommended**: device token and notifications are sent to SimpleX Chat notification server, but not the message content, size or who it is from." = "**Suositus**: laitetunnus ja ilmoitukset lähetetään SimpleX Chat -ilmoituspalvelimelle, mutta ei viestin sisältöä, kokoa tai sitä, keneltä se on peräisin."; -/* No comment provided by engineer. */ -"**Scan QR code**: to connect to your contact in person or via video call." = "**Skannaa QR-koodi**: muodosta yhteys kontaktiisi henkilökohtaisesti tai videopuhelun kautta."; - /* No comment provided by engineer. */ "**Warning**: Instant push notifications require passphrase saved in Keychain." = "**Varoitus**: Välittömät push-ilmoitukset vaativat tunnuslauseen, joka on tallennettu Keychainiin."; @@ -244,9 +235,6 @@ /* time interval */ "1 week" = "1 viikko"; -/* No comment provided by engineer. */ -"1-time link" = "Kertakäyttölinkki"; - /* No comment provided by engineer. */ "5 minutes" = "5 minuuttia"; @@ -384,7 +372,7 @@ "Allow disappearing messages only if your contact allows it to you." = "Salli katoavat viestit vain, jos kontaktisi sallii sen sinulle."; /* No comment provided by engineer. */ -"Allow irreversible message deletion only if your contact allows it to you." = "Salli peruuttamaton viestien poisto vain, jos kontaktisi sallii ne sinulle."; +"Allow irreversible message deletion only if your contact allows it to you. (24 hours)" = "Salli peruuttamaton viestien poisto vain, jos kontaktisi sallii ne sinulle. (24 tuntia)"; /* No comment provided by engineer. */ "Allow message reactions only if your contact allows them." = "Salli reaktiot viesteihin vain, jos kontaktisi sallii ne."; @@ -399,7 +387,7 @@ "Allow sending disappearing messages." = "Salli katoavien viestien lähettäminen."; /* No comment provided by engineer. */ -"Allow to irreversibly delete sent messages." = "Salli lähetettyjen viestien peruuttamaton poistaminen."; +"Allow to irreversibly delete sent messages. (24 hours)" = "Salli lähetettyjen viestien peruuttamaton poistaminen. (24 tuntia)"; /* No comment provided by engineer. */ "Allow to send files and media." = "Salli tiedostojen ja median lähettäminen."; @@ -420,7 +408,7 @@ "Allow your contacts to call you." = "Salli kontaktiesi soittaa sinulle."; /* No comment provided by engineer. */ -"Allow your contacts to irreversibly delete sent messages." = "Salli kontaktiesi poistaa lähetetyt viestit peruuttamattomasti."; +"Allow your contacts to irreversibly delete sent messages. (24 hours)" = "Salli kontaktiesi poistaa lähetetyt viestit peruuttamattomasti. (24 tuntia)"; /* No comment provided by engineer. */ "Allow your contacts to send disappearing messages." = "Salli kontaktiesi lähettää katoavia viestejä."; @@ -528,7 +516,7 @@ "Both you and your contact can add message reactions." = "Sekä sinä että kontaktisi voivat käyttää viestireaktioita."; /* No comment provided by engineer. */ -"Both you and your contact can irreversibly delete sent messages." = "Sekä sinä että kontaktisi voitte peruuttamattomasti poistaa lähetetyt viestit."; +"Both you and your contact can irreversibly delete sent messages. (24 hours)" = "Sekä sinä että kontaktisi voitte peruuttamattomasti poistaa lähetetyt viestit. (24 tuntia)"; /* No comment provided by engineer. */ "Both you and your contact can make calls." = "Sekä sinä että kontaktisi voitte soittaa puheluita."; @@ -557,9 +545,6 @@ /* No comment provided by engineer. */ "Calls" = "Puhelut"; -/* No comment provided by engineer. */ -"Can't delete user profile!" = "Käyttäjäprofiilia ei voi poistaa!"; - /* No comment provided by engineer. */ "Can't invite contact!" = "Kontaktia ei voi kutsua!"; @@ -720,9 +705,6 @@ /* No comment provided by engineer. */ "Connect via link" = "Yhdistä linkin kautta"; -/* No comment provided by engineer. */ -"Connect via link / QR code" = "Yhdistä linkillä / QR-koodilla"; - /* No comment provided by engineer. */ "Connect via one-time link" = "Yhdistä kertalinkillä"; @@ -837,9 +819,6 @@ /* No comment provided by engineer. */ "Create new profile in [desktop app](https://simplex.chat/downloads/). 💻" = "Luo uusi profiili [työpöytäsovelluksessa](https://simplex.chat/downloads/). 💻"; -/* No comment provided by engineer. */ -"Create one-time invitation link" = "Luo kertakutsulinkki"; - /* server test step */ "Create queue" = "Luo jono"; @@ -1603,7 +1582,7 @@ "Group members can add message reactions." = "Ryhmän jäsenet voivat lisätä viestireaktioita."; /* No comment provided by engineer. */ -"Group members can irreversibly delete sent messages." = "Ryhmän jäsenet voivat poistaa lähetetyt viestit peruuttamattomasti."; +"Group members can irreversibly delete sent messages. (24 hours)" = "Ryhmän jäsenet voivat poistaa lähetetyt viestit peruuttamattomasti. (24 tuntia)"; /* No comment provided by engineer. */ "Group members can send direct messages." = "Ryhmän jäsenet voivat lähettää suoraviestejä."; @@ -1695,9 +1674,6 @@ /* No comment provided by engineer. */ "If you can't meet in person, show QR code in a video call, or share the link." = "Jos et voi tavata henkilökohtaisesti, näytä QR-koodi videopuhelussa tai jaa linkki."; -/* No comment provided by engineer. */ -"If you cannot meet in person, you can **scan QR code in the video call**, or your contact can share an invitation link." = "Jos et voi tavata henkilökohtaisesti, voit **skannata QR-koodin videopuhelussa** tai kontaktisi voi jakaa kutsulinkin."; - /* No comment provided by engineer. */ "If you enter this passcode when opening the app, all app data will be irreversibly removed!" = "Jos syötät tämän pääsykoodin sovellusta avatessasi, kaikki sovelluksen tiedot poistetaan peruuttamattomasti!"; @@ -1938,6 +1914,9 @@ /* No comment provided by engineer. */ "Live messages" = "Live-viestit"; +/* No comment provided by engineer. */ +"Local" = "Paikallinen"; + /* No comment provided by engineer. */ "Local name" = "Paikallinen nimi"; @@ -2198,9 +2177,6 @@ /* No comment provided by engineer. */ "Off" = "Pois"; -/* No comment provided by engineer. */ -"Off (Local)" = "Pois (Paikallinen)"; - /* feature offered item */ "offered %@" = "tarjottu %@"; @@ -2247,7 +2223,7 @@ "Only you can add message reactions." = "Vain sinä voit lisätä viestireaktioita."; /* No comment provided by engineer. */ -"Only you can irreversibly delete messages (your contact can mark them for deletion)." = "Vain sinä voit poistaa viestejä peruuttamattomasti (kontaktisi voi merkitä ne poistettavaksi)."; +"Only you can irreversibly delete messages (your contact can mark them for deletion). (24 hours)" = "Vain sinä voit poistaa viestejä peruuttamattomasti (kontaktisi voi merkitä ne poistettavaksi). (24 tuntia)"; /* No comment provided by engineer. */ "Only you can make calls." = "Vain sinä voit soittaa puheluita."; @@ -2262,7 +2238,7 @@ "Only your contact can add message reactions." = "Vain kontaktisi voi lisätä viestireaktioita."; /* No comment provided by engineer. */ -"Only your contact can irreversibly delete messages (you can mark them for deletion)." = "Vain kontaktisi voi poistaa viestejä peruuttamattomasti (voit merkitä ne poistettavaksi)."; +"Only your contact can irreversibly delete messages (you can mark them for deletion). (24 hours)" = "Vain kontaktisi voi poistaa viestejä peruuttamattomasti (voit merkitä ne poistettavaksi). (24 tuntia)"; /* No comment provided by engineer. */ "Only your contact can make calls." = "Vain kontaktisi voi soittaa puheluita."; @@ -2288,9 +2264,6 @@ /* No comment provided by engineer. */ "Open-source protocol and code – anybody can run the servers." = "Avoimen lähdekoodin protokolla ja koodi - kuka tahansa voi käyttää palvelimia."; -/* No comment provided by engineer. */ -"Opening database…" = "Avataan tietokantaa…"; - /* member role */ "owner" = "omistaja"; @@ -2312,18 +2285,9 @@ /* No comment provided by engineer. */ "Password to show" = "Salasana näytettäväksi"; -/* No comment provided by engineer. */ -"Paste" = "Liitä"; - /* No comment provided by engineer. */ "Paste image" = "Liitä kuva"; -/* No comment provided by engineer. */ -"Paste received link" = "Liitä vastaanotettu linkki"; - -/* placeholder */ -"Paste the link you received to connect with your contact." = "Liitä saamasi linkki, jonka avulla voit muodostaa yhteyden kontaktiisi."; - /* No comment provided by engineer. */ "peer-to-peer" = "vertais"; @@ -2867,9 +2831,6 @@ /* No comment provided by engineer. */ "Share link" = "Jaa linkki"; -/* No comment provided by engineer. */ -"Share one-time invitation link" = "Jaa kertakutsulinkki"; - /* No comment provided by engineer. */ "Share with contacts" = "Jaa kontaktien kanssa"; @@ -2942,9 +2903,6 @@ /* notification title */ "Somebody" = "Joku"; -/* No comment provided by engineer. */ -"Start a new chat" = "Aloita uusi keskustelu"; - /* No comment provided by engineer. */ "Start chat" = "Aloita keskustelu"; @@ -3104,12 +3062,6 @@ /* No comment provided by engineer. */ "Theme" = "Teema"; -/* No comment provided by engineer. */ -"There should be at least one user profile." = "Käyttäjäprofiileja tulee olla vähintään yksi."; - -/* No comment provided by engineer. */ -"There should be at least one visible user profile." = "Näkyviä käyttäjäprofiileja tulee olla vähintään yksi."; - /* No comment provided by engineer. */ "These settings are for your current profile **%@**." = "Nämä asetukset koskevat nykyistä profiiliasi **%@**."; @@ -3179,9 +3131,6 @@ /* No comment provided by engineer. */ "Turn off" = "Sammuta"; -/* No comment provided by engineer. */ -"Turn off notifications?" = "Kytke ilmoitukset pois päältä?"; - /* No comment provided by engineer. */ "Turn on" = "Kytke päälle"; @@ -3449,9 +3398,6 @@ /* No comment provided by engineer. */ "You can accept calls from lock screen, without device and app authentication." = "Voit vastaanottaa puheluita lukitusnäytöltä ilman laitteen ja sovelluksen todennusta."; -/* No comment provided by engineer. */ -"You can also connect by clicking the link. If it opens in the browser, click **Open in mobile app** button." = "Voit myös muodostaa yhteyden klikkaamalla linkkiä. Jos se avautuu selaimessa, napsauta **Avaa mobiilisovelluksessa**-painiketta."; - /* No comment provided by engineer. */ "You can create it later" = "Voit luoda sen myöhemmin"; @@ -3602,9 +3548,6 @@ /* No comment provided by engineer. */ "Your contacts can allow full message deletion." = "Kontaktisi voivat sallia viestien täydellisen poistamisen."; -/* No comment provided by engineer. */ -"Your contacts in SimpleX will see it.\nYou can change it in Settings." = "Kontaktisi SimpleX:ssä näkevät sen.\nVoit muuttaa sitä Asetuksista."; - /* No comment provided by engineer. */ "Your contacts will remain connected." = "Kontaktisi pysyvät yhdistettyinä."; diff --git a/apps/ios/fr.lproj/Localizable.strings b/apps/ios/fr.lproj/Localizable.strings index 470e23b4fc..fb202c4f2f 100644 --- a/apps/ios/fr.lproj/Localizable.strings +++ b/apps/ios/fr.lproj/Localizable.strings @@ -64,11 +64,14 @@ /* No comment provided by engineer. */ "[Star on GitHub](https://github.com/simplex-chat/simplex-chat)" = "[Star sur GitHub](https://github.com/simplex-chat/simplex-chat)"; +/* No comment provided by engineer. */ +"**Add contact**: to create a new invitation link, or connect via a link you received." = "**Ajouter un contact** : pour créer un nouveau lien d'invitation ou vous connecter via un lien que vous avez reçu."; + /* No comment provided by engineer. */ "**Add new contact**: to create your one-time QR Code for your contact." = "**Ajouter un nouveau contact** : pour créer un lien ou code QR unique pour votre contact."; /* No comment provided by engineer. */ -"**Create link / QR code** for your contact to use." = "**Créer un lien / code QR** que votre contact pourra utiliser."; +"**Create group**: to create a new group." = "**Créer un groupe** : pour créer un nouveau groupe."; /* No comment provided by engineer. */ "**e2e encrypted** audio call" = "appel audio **chiffré de bout en bout**"; @@ -82,18 +85,12 @@ /* No comment provided by engineer. */ "**Most private**: do not use SimpleX Chat notifications server, check messages periodically in the background (depends on how often you use the app)." = "**Confidentiel** : ne pas utiliser le serveur de notifications SimpleX, vérification de nouveaux messages periodiquement en arrière plan (dépend de l'utilisation de l'app)."; -/* No comment provided by engineer. */ -"**Paste received link** or open it in the browser and tap **Open in mobile app**." = "**Collez le lien reçu** ou ouvrez-le dans votre navigateur et appuyez sur **Open in mobile app**."; - /* No comment provided by engineer. */ "**Please note**: you will NOT be able to recover or change passphrase if you lose it." = "**Veuillez noter** : vous NE pourrez PAS récupérer ou modifier votre phrase secrète si vous la perdez."; /* No comment provided by engineer. */ "**Recommended**: device token and notifications are sent to SimpleX Chat notification server, but not the message content, size or who it is from." = "**Recommandé** : le token de l'appareil et les notifications sont envoyés au serveur de notifications SimpleX, mais pas le contenu du message, sa taille ou son auteur."; -/* No comment provided by engineer. */ -"**Scan QR code**: to connect to your contact in person or via video call." = "**Scanner le code QR** : pour vous connecter à votre contact en personne ou par appel vidéo."; - /* No comment provided by engineer. */ "**Warning**: Instant push notifications require passphrase saved in Keychain." = "**Avertissement** : les notifications push instantanées nécessitent une phrase secrète enregistrée dans la keychain."; @@ -280,9 +277,6 @@ /* time interval */ "1 week" = "1 semaine"; -/* No comment provided by engineer. */ -"1-time link" = "Lien à usage unique"; - /* No comment provided by engineer. */ "5 minutes" = "5 minutes"; @@ -350,6 +344,9 @@ /* No comment provided by engineer. */ "Add address to your profile, so that your contacts can share it with other people. Profile update will be sent to your contacts." = "Ajoutez une adresse à votre profil, afin que vos contacts puissent la partager avec d'autres personnes. La mise à jour du profil sera envoyée à vos contacts."; +/* No comment provided by engineer. */ +"Add contact" = "Ajouter le contact"; + /* No comment provided by engineer. */ "Add preset servers" = "Ajouter des serveurs prédéfinis"; @@ -401,6 +398,9 @@ /* No comment provided by engineer. */ "All group members will remain connected." = "Tous les membres du groupe resteront connectés."; +/* No comment provided by engineer. */ +"All messages will be deleted - this cannot be undone!" = "Tous les messages seront supprimés - il n'est pas possible de revenir en arrière !"; + /* No comment provided by engineer. */ "All messages will be deleted - this cannot be undone! The messages will be deleted ONLY for you." = "Tous les messages seront supprimés - impossible de revenir en arrière ! Les messages seront supprimés UNIQUEMENT pour vous."; @@ -423,7 +423,7 @@ "Allow disappearing messages only if your contact allows it to you." = "Autorise les messages éphémères seulement si votre contact vous l’autorise."; /* No comment provided by engineer. */ -"Allow irreversible message deletion only if your contact allows it to you." = "Autoriser la suppression irréversible des messages uniquement si votre contact vous l'autorise."; +"Allow irreversible message deletion only if your contact allows it to you. (24 hours)" = "Autoriser la suppression irréversible des messages uniquement si votre contact vous l'autorise. (24 heures)"; /* No comment provided by engineer. */ "Allow message reactions only if your contact allows them." = "Autoriser les réactions aux messages uniquement si votre contact les autorise."; @@ -438,7 +438,7 @@ "Allow sending disappearing messages." = "Autorise l’envoi de messages éphémères."; /* No comment provided by engineer. */ -"Allow to irreversibly delete sent messages." = "Autoriser la suppression irréversible de messages envoyés."; +"Allow to irreversibly delete sent messages. (24 hours)" = "Autoriser la suppression irréversible de messages envoyés. (24 heures)"; /* No comment provided by engineer. */ "Allow to send files and media." = "Permet l'envoi de fichiers et de médias."; @@ -459,7 +459,7 @@ "Allow your contacts to call you." = "Autorise vos contacts à vous appeler."; /* No comment provided by engineer. */ -"Allow your contacts to irreversibly delete sent messages." = "Autorise vos contacts à supprimer de manière irréversible les messages envoyés."; +"Allow your contacts to irreversibly delete sent messages. (24 hours)" = "Autorise vos contacts à supprimer de manière irréversible les messages envoyés. (24 heures)"; /* No comment provided by engineer. */ "Allow your contacts to send disappearing messages." = "Autorise votre contact à envoyer des messages éphémères."; @@ -603,7 +603,7 @@ "Both you and your contact can add message reactions." = "Vous et votre contact pouvez ajouter des réactions aux messages."; /* No comment provided by engineer. */ -"Both you and your contact can irreversibly delete sent messages." = "Vous et votre contact êtes tous deux en mesure de supprimer de manière irréversible les messages envoyés."; +"Both you and your contact can irreversibly delete sent messages. (24 hours)" = "Vous et votre contact êtes tous deux en mesure de supprimer de manière irréversible les messages envoyés. (24 heures)"; /* No comment provided by engineer. */ "Both you and your contact can make calls." = "Vous et votre contact pouvez tous deux passer des appels."; @@ -636,7 +636,7 @@ "Calls" = "Appels"; /* No comment provided by engineer. */ -"Can't delete user profile!" = "Impossible de supprimer le profil d'utilisateur !"; +"Camera not available" = "Caméra non disponible"; /* No comment provided by engineer. */ "Can't invite contact!" = "Impossible d'inviter le contact !"; @@ -723,11 +723,14 @@ /* No comment provided by engineer. */ "Chat is stopped" = "Le chat est arrêté"; +/* No comment provided by engineer. */ +"Chat is stopped. If you already used this database on another device, you should transfer it back before starting chat." = "Le chat est arrêté. Si vous avez déjà utilisé cette base de données sur un autre appareil, vous devez la transférer à nouveau avant de démarrer le chat."; + /* No comment provided by engineer. */ "Chat preferences" = "Préférences de chat"; /* No comment provided by engineer. */ -"Chats" = "Chats"; +"Chats" = "Discussions"; /* No comment provided by engineer. */ "Check server address and try again." = "Vérifiez l'adresse du serveur et réessayez."; @@ -750,6 +753,9 @@ /* No comment provided by engineer. */ "Clear conversation?" = "Effacer la conversation ?"; +/* No comment provided by engineer. */ +"Clear private notes?" = "Effacer les notes privées ?"; + /* No comment provided by engineer. */ "Clear verification" = "Retirer la vérification"; @@ -796,7 +802,7 @@ "Connect incognito" = "Se connecter incognito"; /* No comment provided by engineer. */ -"Connect to desktop" = "Se connecter au bureau"; +"Connect to desktop" = "Connexion au bureau"; /* No comment provided by engineer. */ "connect to SimpleX Chat developers." = "se connecter aux developpeurs de SimpleX Chat."; @@ -816,9 +822,6 @@ /* No comment provided by engineer. */ "Connect via link" = "Se connecter via un lien"; -/* No comment provided by engineer. */ -"Connect via link / QR code" = "Se connecter via un lien / code QR"; - /* No comment provided by engineer. */ "Connect via one-time link" = "Se connecter via un lien unique"; @@ -891,6 +894,9 @@ /* connection information */ "connection:%@" = "connexion : %@"; +/* profile update event chat item */ +"contact %@ changed to %@" = "le contact %1$@ est devenu %2$@"; + /* No comment provided by engineer. */ "Contact allows" = "Votre contact autorise"; @@ -960,9 +966,6 @@ /* No comment provided by engineer. */ "Create new profile in [desktop app](https://simplex.chat/downloads/). 💻" = "Créer un nouveau profil sur [l'application de bureau](https://simplex.chat/downloads/). 💻"; -/* No comment provided by engineer. */ -"Create one-time invitation link" = "Créer un lien d'invitation unique"; - /* No comment provided by engineer. */ "Create profile" = "Créer le profil"; @@ -978,9 +981,18 @@ /* No comment provided by engineer. */ "Create your profile" = "Créez votre profil"; +/* No comment provided by engineer. */ +"Created at" = "Créé à"; + +/* copied message info */ +"Created at: %@" = "Créé à : %@"; + /* No comment provided by engineer. */ "Created on %@" = "Créé le %@"; +/* No comment provided by engineer. */ +"Creating link…" = "Création d'un lien…"; + /* No comment provided by engineer. */ "creator" = "créateur"; @@ -1299,6 +1311,9 @@ /* No comment provided by engineer. */ "Do it later" = "Faites-le plus tard"; +/* No comment provided by engineer. */ +"Do not send history to new members." = "Ne pas envoyer d'historique aux nouveaux membres."; + /* No comment provided by engineer. */ "Do NOT use SimpleX for emergency calls." = "N'utilisez PAS SimpleX pour les appels d'urgence."; @@ -1344,6 +1359,9 @@ /* No comment provided by engineer. */ "Enable automatic message deletion?" = "Activer la suppression automatique des messages ?"; +/* No comment provided by engineer. */ +"Enable camera access" = "Autoriser l'accès à la caméra"; + /* No comment provided by engineer. */ "Enable for all" = "Activer pour tous"; @@ -1398,6 +1416,9 @@ /* notification */ "Encrypted message or another event" = "Message chiffrée ou autre événement"; +/* notification */ +"Encrypted message: app is stopped" = "Message chiffré : l'application est arrêtée"; + /* notification */ "Encrypted message: database error" = "Message chiffrée : erreur de base de données"; @@ -1518,6 +1539,9 @@ /* No comment provided by engineer. */ "Error creating member contact" = "Erreur lors de la création du contact du membre"; +/* No comment provided by engineer. */ +"Error creating message" = "Erreur lors de la création du message"; + /* No comment provided by engineer. */ "Error creating profile!" = "Erreur lors de la création du profil !"; @@ -1569,6 +1593,9 @@ /* No comment provided by engineer. */ "Error loading %@ servers" = "Erreur lors du chargement des serveurs %@"; +/* No comment provided by engineer. */ +"Error opening chat" = "Erreur lors de l'ouverture du chat"; + /* No comment provided by engineer. */ "Error receiving file" = "Erreur lors de la réception du fichier"; @@ -1593,6 +1620,9 @@ /* No comment provided by engineer. */ "Error saving user password" = "Erreur d'enregistrement du mot de passe de l'utilisateur"; +/* No comment provided by engineer. */ +"Error scanning code: %@" = "Erreur lors du scan du code : %@"; + /* No comment provided by engineer. */ "Error sending email" = "Erreur lors de l'envoi de l'e-mail"; @@ -1648,7 +1678,7 @@ "event happened" = "event happened"; /* No comment provided by engineer. */ -"Exit without saving" = "Quitter sans sauvegarder"; +"Exit without saving" = "Quitter sans enregistrer"; /* chat item action */ "Expand" = "Développer"; @@ -1708,7 +1738,7 @@ "Finally, we have them! 🚀" = "Enfin, les voilà ! 🚀"; /* No comment provided by engineer. */ -"Find chats faster" = "Trouver des messages plus rapidement"; +"Find chats faster" = "Recherche de message plus rapide"; /* No comment provided by engineer. */ "Fix" = "Réparer"; @@ -1798,7 +1828,7 @@ "Group members can add message reactions." = "Les membres du groupe peuvent ajouter des réactions aux messages."; /* No comment provided by engineer. */ -"Group members can irreversibly delete sent messages." = "Les membres du groupe peuvent supprimer de manière irréversible les messages envoyés."; +"Group members can irreversibly delete sent messages. (24 hours)" = "Les membres du groupe peuvent supprimer de manière irréversible les messages envoyés. (24 heures)"; /* No comment provided by engineer. */ "Group members can send direct messages." = "Les membres du groupe peuvent envoyer des messages directs."; @@ -1866,6 +1896,9 @@ /* No comment provided by engineer. */ "History" = "Historique"; +/* No comment provided by engineer. */ +"History is not sent to new members." = "L'historique n'est pas envoyé aux nouveaux membres."; + /* time unit */ "hours" = "heures"; @@ -1890,9 +1923,6 @@ /* No comment provided by engineer. */ "If you can't meet in person, show QR code in a video call, or share the link." = "Si vous ne pouvez pas vous rencontrer en personne, montrez le code QR lors d'un appel vidéo ou partagez le lien."; -/* No comment provided by engineer. */ -"If you cannot meet in person, you can **scan QR code in the video call**, or your contact can share an invitation link." = "Si vous ne pouvez pas voir la personne, vous pouvez **scanner le code QR dans un appel vidéo**, ou votre contact peut vous partager un lien d'invitation."; - /* No comment provided by engineer. */ "If you enter this passcode when opening the app, all app data will be irreversibly removed!" = "Si vous saisissez ce code à l'ouverture de l'application, toutes les données de l'application seront irréversiblement supprimées !"; @@ -1926,6 +1956,9 @@ /* No comment provided by engineer. */ "Import database" = "Importer la base de données"; +/* No comment provided by engineer. */ +"Improved message delivery" = "Amélioration de la transmission des messages"; + /* No comment provided by engineer. */ "Improved privacy and security" = "Une meilleure sécurité et protection de la vie privée"; @@ -2010,9 +2043,21 @@ /* invalid chat item */ "invalid data" = "données invalides"; +/* No comment provided by engineer. */ +"Invalid display name!" = "Nom d'affichage invalide !"; + +/* No comment provided by engineer. */ +"Invalid link" = "Lien invalide"; + /* No comment provided by engineer. */ "Invalid name!" = "Nom invalide !"; +/* No comment provided by engineer. */ +"Invalid QR code" = "Code QR invalide"; + +/* No comment provided by engineer. */ +"Invalid response" = "Réponse invalide"; + /* No comment provided by engineer. */ "Invalid server address!" = "Adresse de serveur invalide !"; @@ -2091,6 +2136,9 @@ /* No comment provided by engineer. */ "Join group" = "Rejoindre le groupe"; +/* No comment provided by engineer. */ +"Join group conversations" = "Participez aux conversations de groupe"; + /* No comment provided by engineer. */ "Join group?" = "Rejoindre le groupe ?"; @@ -2106,9 +2154,15 @@ /* No comment provided by engineer. */ "Joining group" = "Entrain de rejoindre le groupe"; +/* No comment provided by engineer. */ +"Keep" = "Conserver"; + /* No comment provided by engineer. */ "Keep the app open to use it from desktop" = "Garder l'application ouverte pour l'utiliser depuis le bureau"; +/* No comment provided by engineer. */ +"Keep unused invitation?" = "Conserver l'invitation inutilisée ?"; + /* No comment provided by engineer. */ "Keep your connections" = "Conserver vos connexions"; @@ -2163,6 +2217,9 @@ /* No comment provided by engineer. */ "Live messages" = "Messages dynamiques"; +/* No comment provided by engineer. */ +"Local" = "Local"; + /* No comment provided by engineer. */ "Local name" = "Nom local"; @@ -2217,6 +2274,9 @@ /* No comment provided by engineer. */ "Member" = "Membre"; +/* profile update event chat item */ +"member %@ changed to %@" = "le membre %1$@ est devenu %2$@"; + /* rcv group event chat item */ "member connected" = "est connecté·e"; @@ -2334,6 +2394,9 @@ /* No comment provided by engineer. */ "never" = "jamais"; +/* No comment provided by engineer. */ +"New chat" = "Nouveau chat"; + /* notification */ "New contact request" = "Nouvelle demande de contact"; @@ -2392,7 +2455,7 @@ "no e2e encryption" = "sans chiffrement de bout en bout"; /* No comment provided by engineer. */ -"No filtered chats" = "Pas de chats filtrés"; +"No filtered chats" = "Aucune discussion filtrés"; /* No comment provided by engineer. */ "No group!" = "Groupe introuvable !"; @@ -2432,18 +2495,18 @@ /* No comment provided by engineer. */ "Off" = "Off"; -/* No comment provided by engineer. */ -"Off (Local)" = "Off (Local)"; +/* feature offered item */ +"offered %@" = "propose %@"; /* feature offered item */ -"offered %@" = "offert %@"; - -/* feature offered item */ -"offered %@: %@" = "offert %1$@ : %2$@"; +"offered %@: %@" = "propose %1$@ : %2$@"; /* No comment provided by engineer. */ "Ok" = "Ok"; +/* No comment provided by engineer. */ +"OK" = "OK"; + /* No comment provided by engineer. */ "Old database" = "Ancienne base de données"; @@ -2481,7 +2544,7 @@ "Only you can add message reactions." = "Vous seul pouvez ajouter des réactions aux messages."; /* No comment provided by engineer. */ -"Only you can irreversibly delete messages (your contact can mark them for deletion)." = "Vous êtes le seul à pouvoir supprimer des messages de manière irréversible (votre contact peut les marquer comme supprimé)."; +"Only you can irreversibly delete messages (your contact can mark them for deletion). (24 hours)" = "Vous êtes le seul à pouvoir supprimer des messages de manière irréversible (votre contact peut les marquer comme supprimé). (24 heures)"; /* No comment provided by engineer. */ "Only you can make calls." = "Vous seul pouvez passer des appels."; @@ -2496,7 +2559,7 @@ "Only your contact can add message reactions." = "Seul votre contact peut ajouter des réactions aux messages."; /* No comment provided by engineer. */ -"Only your contact can irreversibly delete messages (you can mark them for deletion)." = "Seul votre contact peut supprimer de manière irréversible des messages (vous pouvez les marquer comme supprimé)."; +"Only your contact can irreversibly delete messages (you can mark them for deletion). (24 hours)" = "Seul votre contact peut supprimer de manière irréversible des messages (vous pouvez les marquer comme supprimé). (24 heures)"; /* No comment provided by engineer. */ "Only your contact can make calls." = "Seul votre contact peut passer des appels."; @@ -2529,7 +2592,13 @@ "Open-source protocol and code – anybody can run the servers." = "Protocole et code open-source – n'importe qui peut heberger un serveur."; /* No comment provided by engineer. */ -"Opening database…" = "Ouverture de la base de données…"; +"Opening app…" = "Ouverture de l'app…"; + +/* No comment provided by engineer. */ +"Or scan QR code" = "Ou scanner le code QR"; + +/* No comment provided by engineer. */ +"Or show this code" = "Ou présenter ce code"; /* member role */ "owner" = "propriétaire"; @@ -2552,8 +2621,8 @@ /* No comment provided by engineer. */ "Password to show" = "Mot de passe à entrer"; -/* No comment provided by engineer. */ -"Paste" = "Coller"; +/* past/unknown group member */ +"Past member %@" = "Ancien membre %@"; /* No comment provided by engineer. */ "Paste desktop address" = "Coller l'adresse du bureau"; @@ -2562,10 +2631,10 @@ "Paste image" = "Coller l'image"; /* No comment provided by engineer. */ -"Paste received link" = "Coller le lien reçu"; +"Paste link to connect!" = "Collez le lien pour vous connecter !"; -/* placeholder */ -"Paste the link you received to connect with your contact." = "Collez le lien que vous avez reçu dans le cadre ci-dessous pour vous connecter avec votre contact."; +/* No comment provided by engineer. */ +"Paste the link you received" = "Collez le lien que vous avez reçu"; /* No comment provided by engineer. */ "peer-to-peer" = "pair-à-pair"; @@ -2597,6 +2666,9 @@ /* No comment provided by engineer. */ "Please check yours and your contact preferences." = "Veuillez vérifier vos préférences ainsi que celles de votre contact."; +/* No comment provided by engineer. */ +"Please contact developers.\nError: %@" = "Veuillez contacter les développeurs.\nErreur : %@"; + /* No comment provided by engineer. */ "Please contact group admin." = "Veuillez contacter l'administrateur du groupe."; @@ -2648,6 +2720,9 @@ /* No comment provided by engineer. */ "Private filenames" = "Noms de fichiers privés"; +/* name of notes to self */ +"Private notes" = "Notes privées"; + /* No comment provided by engineer. */ "Profile and server connections" = "Profil et connexions au serveur"; @@ -2720,6 +2795,9 @@ /* No comment provided by engineer. */ "Read more in [User Guide](https://simplex.chat/docs/guide/app-settings.html#your-simplex-contact-address)." = "Pour en savoir plus, consultez le [Guide de l'utilisateur](https://simplex.chat/docs/guide/app-settings.html#your-simplex-contact-address)."; +/* No comment provided by engineer. */ +"Read more in [User Guide](https://simplex.chat/docs/guide/chat-profiles.html#incognito-mode)." = "Pour en savoir plus, consultez le [Guide de l'utilisateur](https ://simplex.chat/docs/guide/chat-profiles.html#incognito-mode)."; + /* No comment provided by engineer. */ "Read more in [User Guide](https://simplex.chat/docs/guide/readme.html#connect-to-friends)." = "Pour en savoir plus, consultez le [Guide de l'utilisateur](https://simplex.chat/docs/guide/readme.html#connect-to-friends)."; @@ -2759,6 +2837,9 @@ /* No comment provided by engineer. */ "Receiving via" = "Réception via"; +/* No comment provided by engineer. */ +"Recent history and improved [directory bot](simplex:/contact#/?v=1-4&smp=smp%3A%2F%2Fu2dS9sG8nMNURyZwqASV4yROM28Er0luVTx5X1CsMrU%3D%40smp4.simplex.im%2FeXSPwqTkKyDO3px4fLf1wx3MvPdjdLW3%23%2F%3Fv%3D1-2%26dh%3DMCowBQYDK2VuAyEAaiv6MkMH44L2TcYrt_CsX3ZvM11WgbMEUn0hkIKTOho%253D%26srv%3Do5vmywmrnaxalvz6wi3zicyftgio6psuvyniis6gco6bp6ekl4cqj4id.onion)." = "Historique récent et amélioration du [bot annuaire](simplex:/contact#/?v=1-4&smp=smp%3A%2F%2Fu2dS9sG8nMNURyZwqASV4yROM28Er0luVTx5X1CsMrU%3D%40smp4.simplex.im%2FeXSPwqTkKyDO3px4fLf1wx3MvPdjdLW3%23%2F%3Fv%3D1-2%26dh%3DMCowBQYDK2VuAyEAaiv6MkMH44L2TcYrt_CsX3ZvM11WgbMEUn0hkIKTOho%253D%26srv%3Do5vmywmrnaxalvz6wi3zicyftgio6psuvyniis6gco6bp6ekl4cqj4id.onion)."; + /* No comment provided by engineer. */ "Recipients see updates as you type them." = "Les destinataires voient les mises à jour au fur et à mesure que vous leur écrivez."; @@ -2813,6 +2894,12 @@ /* rcv group event chat item */ "removed %@" = "a retiré %@"; +/* profile update event chat item */ +"removed contact address" = "suppression de l'adresse de contact"; + +/* profile update event chat item */ +"removed profile picture" = "suppression de la photo de profil"; + /* rcv group event chat item */ "removed you" = "vous a retiré"; @@ -2864,6 +2951,9 @@ /* No comment provided by engineer. */ "Restore database error" = "Erreur de restauration de la base de données"; +/* No comment provided by engineer. */ +"Retry" = "Réessayer"; + /* chat item action */ "Reveal" = "Révéler"; @@ -2886,52 +2976,55 @@ "Run chat" = "Exécuter le chat"; /* chat item action */ -"Save" = "Sauvegarder"; +"Save" = "Enregistrer"; /* No comment provided by engineer. */ -"Save (and notify contacts)" = "Sauvegarder (et en informer les contacts)"; +"Save (and notify contacts)" = "Enregistrer (et en informer les contacts)"; /* No comment provided by engineer. */ -"Save and notify contact" = "Sauvegarder et en informer les contacts"; +"Save and notify contact" = "Enregistrer et en informer le contact"; /* No comment provided by engineer. */ -"Save and notify group members" = "Sauvegarder et en informer les membres du groupe"; +"Save and notify group members" = "Enregistrer et en informer les membres du groupe"; /* No comment provided by engineer. */ -"Save and update group profile" = "Sauvegarder et mettre à jour le profil du groupe"; +"Save and update group profile" = "Enregistrer et mettre à jour le profil du groupe"; /* No comment provided by engineer. */ -"Save archive" = "Sauvegarder l'archive"; +"Save archive" = "Enregistrer l'archive"; /* No comment provided by engineer. */ -"Save auto-accept settings" = "Sauvegarder les paramètres d'acceptation automatique"; +"Save auto-accept settings" = "Enregistrer les paramètres de validation automatique"; /* No comment provided by engineer. */ -"Save group profile" = "Sauvegarder le profil du groupe"; +"Save group profile" = "Enregistrer le profil du groupe"; /* No comment provided by engineer. */ -"Save passphrase and open chat" = "Sauvegarder la phrase secrète et ouvrir le chat"; +"Save passphrase and open chat" = "Enregistrer la phrase secrète et ouvrir le chat"; /* No comment provided by engineer. */ -"Save passphrase in Keychain" = "Sauvegarder la phrase secrète dans la keychain"; +"Save passphrase in Keychain" = "Enregistrer la phrase secrète dans la Keychain"; /* No comment provided by engineer. */ -"Save preferences?" = "Sauvegarder les préférences ?"; +"Save preferences?" = "Enregistrer les préférences ?"; /* No comment provided by engineer. */ "Save profile password" = "Enregistrer le mot de passe du profil"; /* No comment provided by engineer. */ -"Save servers" = "Sauvegarder les serveurs"; +"Save servers" = "Enregistrer les serveurs"; /* No comment provided by engineer. */ -"Save servers?" = "Sauvegarder les serveurs ?"; +"Save servers?" = "Enregistrer les serveurs ?"; /* No comment provided by engineer. */ -"Save settings?" = "Sauvegarder les paramètres ?"; +"Save settings?" = "Enregistrer les paramètres ?"; /* No comment provided by engineer. */ -"Save welcome message?" = "Sauvegarder le message d'accueil ?"; +"Save welcome message?" = "Enregistrer le message d'accueil ?"; + +/* message info title */ +"Saved message" = "Message enregistré"; /* No comment provided by engineer. */ "Saved WebRTC ICE servers will be removed" = "Les serveurs WebRTC ICE sauvegardés seront supprimés"; @@ -2943,7 +3036,7 @@ "Scan QR code" = "Scanner un code QR"; /* No comment provided by engineer. */ -"Scan QR code from desktop" = "Scanner le code QR du bureau"; +"Scan QR code from desktop" = "Scannez le code QR du bureau"; /* No comment provided by engineer. */ "Scan security code from your contact's app." = "Scannez le code de sécurité depuis l'application de votre contact."; @@ -2952,7 +3045,13 @@ "Scan server QR code" = "Scanner un code QR de serveur"; /* No comment provided by engineer. */ -"Search" = "Recherche"; +"Search" = "Rechercher"; + +/* No comment provided by engineer. */ +"Search bar accepts invitation links." = "La barre de recherche accepte les liens d'invitation."; + +/* No comment provided by engineer. */ +"Search or paste SimpleX link" = "Rechercher ou coller un lien SimpleX"; /* network option */ "sec" = "sec"; @@ -3027,11 +3126,14 @@ "Send questions and ideas" = "Envoyez vos questions et idées"; /* No comment provided by engineer. */ -"Send receipts" = "Envoyer les justificatifs"; +"Send receipts" = "Envoi de justificatifs"; /* No comment provided by engineer. */ "Send them from gallery or custom keyboards." = "Envoyez-les depuis la phototèque ou des claviers personnalisés."; +/* No comment provided by engineer. */ +"Send up to 100 last messages to new members." = "Envoi des 100 derniers messages aux nouveaux membres."; + /* No comment provided by engineer. */ "Sender cancelled file transfer." = "L'expéditeur a annulé le transfert de fichiers."; @@ -3104,6 +3206,12 @@ /* No comment provided by engineer. */ "Set it instead of system authentication." = "Il permet de remplacer l'authentification du système."; +/* profile update event chat item */ +"set new contact address" = "définir une nouvelle adresse de contact"; + +/* profile update event chat item */ +"set new profile picture" = "définir une nouvelle image de profil"; + /* No comment provided by engineer. */ "Set passcode" = "Définir le code d'accès"; @@ -3135,7 +3243,7 @@ "Share link" = "Partager le lien"; /* No comment provided by engineer. */ -"Share one-time invitation link" = "Partager un lien d'invitation unique"; +"Share this 1-time invite link" = "Partager ce lien d'invitation unique"; /* No comment provided by engineer. */ "Share with contacts" = "Partager avec vos contacts"; @@ -3213,10 +3321,10 @@ "Somebody" = "Quelqu'un"; /* No comment provided by engineer. */ -"Start a new chat" = "Commencer une nouvelle conversation"; +"Start chat" = "Démarrer le chat"; /* No comment provided by engineer. */ -"Start chat" = "Démarrer le chat"; +"Start chat?" = "Lancer le chat ?"; /* No comment provided by engineer. */ "Start migration" = "Démarrer la migration"; @@ -3287,6 +3395,12 @@ /* No comment provided by engineer. */ "Tap to join incognito" = "Appuyez pour rejoindre incognito"; +/* No comment provided by engineer. */ +"Tap to paste link" = "Appuyez pour coller le lien"; + +/* No comment provided by engineer. */ +"Tap to scan" = "Appuyez pour scanner"; + /* No comment provided by engineer. */ "Tap to start a new chat" = "Appuyez ici pour démarrer une nouvelle discussion"; @@ -3332,6 +3446,9 @@ /* No comment provided by engineer. */ "The attempt to change database passphrase was not completed." = "La tentative de modification de la phrase secrète de la base de données n'a pas abouti."; +/* No comment provided by engineer. */ +"The code you scanned is not a SimpleX link QR code." = "Le code scanné n'est pas un code QR de lien SimpleX."; + /* No comment provided by engineer. */ "The connection you accepted will be cancelled!" = "La connexion que vous avez acceptée sera annulée !"; @@ -3374,15 +3491,12 @@ /* No comment provided by engineer. */ "The servers for new connections of your current chat profile **%@**." = "Les serveurs pour les nouvelles connexions de votre profil de chat actuel **%@**."; +/* No comment provided by engineer. */ +"The text you pasted is not a SimpleX link." = "Le texte collé n'est pas un lien SimpleX."; + /* No comment provided by engineer. */ "Theme" = "Thème"; -/* No comment provided by engineer. */ -"There should be at least one user profile." = "Il doit y avoir au moins un profil d'utilisateur."; - -/* No comment provided by engineer. */ -"There should be at least one visible user profile." = "Il doit y avoir au moins un profil d'utilisateur visible."; - /* No comment provided by engineer. */ "These settings are for your current profile **%@**." = "Ces paramètres s'appliquent à votre profil actuel **%@**."; @@ -3402,7 +3516,10 @@ "this contact" = "ce contact"; /* No comment provided by engineer. */ -"This device name" = "Ce nom d'appareil"; +"This device name" = "Nom de cet appareil"; + +/* No comment provided by engineer. */ +"This display name is invalid. Please choose another name." = "Ce nom d'affichage est invalide. Veuillez choisir un autre nom."; /* No comment provided by engineer. */ "This group has over %lld members, delivery receipts are not sent." = "Ce groupe compte plus de %lld membres, les accusés de réception ne sont pas envoyés."; @@ -3465,10 +3582,10 @@ "Trying to connect to the server used to receive messages from this contact." = "Tentative de connexion au serveur utilisé pour recevoir les messages de ce contact."; /* No comment provided by engineer. */ -"Turn off" = "Désactiver"; +"Turkish interface" = "Interface en turc"; /* No comment provided by engineer. */ -"Turn off notifications?" = "Désactiver les notifications ?"; +"Turn off" = "Désactiver"; /* No comment provided by engineer. */ "Turn on" = "Activer"; @@ -3518,6 +3635,9 @@ /* No comment provided by engineer. */ "Unknown error" = "Erreur inconnue"; +/* No comment provided by engineer. */ +"unknown status" = "statut inconnu"; + /* No comment provided by engineer. */ "Unless you use iOS call interface, enable Do Not Disturb mode to avoid interruptions." = "À moins que vous utilisiez l'interface d'appel d'iOS, activez le mode \"Ne pas déranger\" pour éviter les interruptions."; @@ -3542,6 +3662,9 @@ /* No comment provided by engineer. */ "Unread" = "Non lu"; +/* No comment provided by engineer. */ +"Up to 100 last messages are sent to new members." = "Les 100 derniers messages sont envoyés aux nouveaux membres."; + /* No comment provided by engineer. */ "Update" = "Mise à jour"; @@ -3560,6 +3683,9 @@ /* rcv group event chat item */ "updated group profile" = "mise à jour du profil de groupe"; +/* profile update event chat item */ +"updated profile" = "profil mis à jour"; + /* No comment provided by engineer. */ "Updating settings will re-connect the client to all servers." = "La mise à jour des ces paramètres reconnectera le client à tous les serveurs."; @@ -3585,7 +3711,7 @@ "Use for new connections" = "Utiliser pour les nouvelles connexions"; /* No comment provided by engineer. */ -"Use from desktop" = "Utilisation depuis le bureau"; +"Use from desktop" = "Accès au bureau"; /* No comment provided by engineer. */ "Use iOS call interface" = "Utiliser l'interface d'appel d'iOS"; @@ -3593,6 +3719,9 @@ /* No comment provided by engineer. */ "Use new incognito profile" = "Utiliser un nouveau profil incognito"; +/* No comment provided by engineer. */ +"Use only local notifications?" = "Utilisation de notifications locales uniquement ?"; + /* No comment provided by engineer. */ "Use server" = "Utiliser ce serveur"; @@ -3665,6 +3794,9 @@ /* No comment provided by engineer. */ "View security code" = "Afficher le code de sécurité"; +/* chat feature */ +"Visible history" = "Historique visible"; + /* No comment provided by engineer. */ "Voice message…" = "Message vocal…"; @@ -3728,9 +3860,15 @@ /* No comment provided by engineer. */ "When you share an incognito profile with somebody, this profile will be used for the groups they invite you to." = "Lorsque vous partagez un profil incognito avec quelqu'un, ce profil sera utilisé pour les groupes auxquels il vous invite."; +/* No comment provided by engineer. */ +"With encrypted files and media." = "Avec les fichiers et les médias chiffrés."; + /* No comment provided by engineer. */ "With optional welcome message." = "Avec message de bienvenue facultatif."; +/* No comment provided by engineer. */ +"With reduced battery usage." = "Consommation réduite de la batterie."; + /* No comment provided by engineer. */ "Wrong database passphrase" = "Mauvaise phrase secrète pour la base de données"; @@ -3794,9 +3932,6 @@ /* No comment provided by engineer. */ "You can accept calls from lock screen, without device and app authentication." = "Vous pouvez accepter des appels à partir de l'écran de verrouillage, sans authentification de l'appareil ou de l'application."; -/* No comment provided by engineer. */ -"You can also connect by clicking the link. If it opens in the browser, click **Open in mobile app** button." = "Vous pouvez également vous connecter en cliquant sur le lien. S'il s'ouvre dans le navigateur, cliquez sur le bouton **Open in mobile app**."; - /* No comment provided by engineer. */ "You can create it later" = "Vous pouvez la créer plus tard"; @@ -3809,6 +3944,9 @@ /* No comment provided by engineer. */ "You can hide or mute a user profile - swipe it to the right." = "Vous pouvez masquer ou mettre en sourdine un profil d'utilisateur - faites-le glisser vers la droite."; +/* No comment provided by engineer. */ +"You can make it visible to your SimpleX contacts via Settings." = "Vous pouvez le rendre visible à vos contacts SimpleX via Paramètres."; + /* notification body */ "You can now send messages to %@" = "Vous pouvez maintenant envoyer des messages à %@"; @@ -3833,6 +3971,9 @@ /* No comment provided by engineer. */ "You can use markdown to format messages:" = "Vous pouvez utiliser le format markdown pour mettre en forme les messages :"; +/* No comment provided by engineer. */ +"You can view invitation link again in connection details." = "Vous pouvez à nouveau consulter le lien d'invitation dans les détails de la connexion."; + /* No comment provided by engineer. */ "You can't send messages!" = "Vous ne pouvez pas envoyer de messages !"; @@ -3959,9 +4100,6 @@ /* No comment provided by engineer. */ "Your contacts can allow full message deletion." = "Vos contacts peuvent autoriser la suppression complète des messages."; -/* No comment provided by engineer. */ -"Your contacts in SimpleX will see it.\nYou can change it in Settings." = "Vos contacts dans SimpleX la verront.\nVous pouvez modifier ce choix dans les Paramètres."; - /* No comment provided by engineer. */ "Your contacts will remain connected." = "Vos contacts resteront connectés."; diff --git a/apps/ios/it.lproj/Localizable.strings b/apps/ios/it.lproj/Localizable.strings index 274b909da2..85808267e6 100644 --- a/apps/ios/it.lproj/Localizable.strings +++ b/apps/ios/it.lproj/Localizable.strings @@ -62,13 +62,16 @@ "[Send us email](mailto:chat@simplex.chat)" = "[Inviaci un'email](mailto:chat@simplex.chat)"; /* No comment provided by engineer. */ -"[Star on GitHub](https://github.com/simplex-chat/simplex-chat)" = "[Stella su GitHub](https://github.com/simplex-chat/simplex-chat)"; +"[Star on GitHub](https://github.com/simplex-chat/simplex-chat)" = "[Dai una stella su GitHub](https://github.com/simplex-chat/simplex-chat)"; + +/* No comment provided by engineer. */ +"**Add contact**: to create a new invitation link, or connect via a link you received." = "**Aggiungi contatto**: per creare un nuovo link di invito o connetterti tramite un link che hai ricevuto."; /* No comment provided by engineer. */ "**Add new contact**: to create your one-time QR Code for your contact." = "**Aggiungi un contatto**: per creare il tuo codice QR o link una tantum per il tuo contatto."; /* No comment provided by engineer. */ -"**Create link / QR code** for your contact to use." = "**Crea link / codice QR** da usare per il tuo contatto."; +"**Create group**: to create a new group." = "**Crea gruppo**: per creare un nuovo gruppo."; /* No comment provided by engineer. */ "**e2e encrypted** audio call" = "Chiamata **crittografata e2e**"; @@ -82,18 +85,12 @@ /* No comment provided by engineer. */ "**Most private**: do not use SimpleX Chat notifications server, check messages periodically in the background (depends on how often you use the app)." = "**Il più privato**: non usare il server di notifica di SimpleX Chat, controlla i messaggi periodicamente in secondo piano (dipende da quanto spesso usi l'app)."; -/* No comment provided by engineer. */ -"**Paste received link** or open it in the browser and tap **Open in mobile app**." = "**Incolla il link ricevuto** o aprilo nel browser e tocca **Apri in app mobile**."; - /* No comment provided by engineer. */ "**Please note**: you will NOT be able to recover or change passphrase if you lose it." = "**Nota bene**: NON potrai recuperare o cambiare la password se la perdi."; /* No comment provided by engineer. */ "**Recommended**: device token and notifications are sent to SimpleX Chat notification server, but not the message content, size or who it is from." = "**Consigliato**: vengono inviati il token del dispositivo e le notifiche al server di notifica di SimpleX Chat, ma non il contenuto del messaggio,la sua dimensione o il suo mittente."; -/* No comment provided by engineer. */ -"**Scan QR code**: to connect to your contact in person or via video call." = "**Scansiona codice QR**: per connetterti al contatto di persona o via videochiamata."; - /* No comment provided by engineer. */ "**Warning**: Instant push notifications require passphrase saved in Keychain." = "**Attenzione**: le notifiche push istantanee richiedono una password salvata nel portachiavi."; @@ -131,7 +128,7 @@ "%@ and %@" = "%@ e %@"; /* No comment provided by engineer. */ -"%@ and %@ connected" = "%@ e %@ sono connessi/e"; +"%@ and %@ connected" = "%@ e %@ si sono connessi/e"; /* copied message info, <sender> at <time> */ "%@ at %@:" = "%1$@ alle %2$@:"; @@ -158,7 +155,7 @@ "%@, %@ and %lld members" = "%@, %@ e %lld membri"; /* No comment provided by engineer. */ -"%@, %@ and %lld other members connected" = "%@, %@ e altri %lld membri sono connessi"; +"%@, %@ and %lld other members connected" = "%@, %@ e altri %lld membri si sono connessi"; /* copied message info */ "%@:" = "%@:"; @@ -205,6 +202,9 @@ /* No comment provided by engineer. */ "%lld messages blocked" = "%lld messaggi bloccati"; +/* No comment provided by engineer. */ +"%lld messages blocked by admin" = "%lld messaggi bloccati dall'amministratore"; + /* No comment provided by engineer. */ "%lld messages marked deleted" = "%lld messaggi contrassegnati eliminati"; @@ -280,9 +280,6 @@ /* time interval */ "1 week" = "1 settimana"; -/* No comment provided by engineer. */ -"1-time link" = "Link una tantum"; - /* No comment provided by engineer. */ "5 minutes" = "5 minuti"; @@ -350,6 +347,9 @@ /* No comment provided by engineer. */ "Add address to your profile, so that your contacts can share it with other people. Profile update will be sent to your contacts." = "Aggiungi l'indirizzo al tuo profilo, in modo che i tuoi contatti possano condividerlo con altre persone. L'aggiornamento del profilo verrà inviato ai tuoi contatti."; +/* No comment provided by engineer. */ +"Add contact" = "Aggiungi contatto"; + /* No comment provided by engineer. */ "Add preset servers" = "Aggiungi server preimpostati"; @@ -401,6 +401,9 @@ /* No comment provided by engineer. */ "All group members will remain connected." = "Tutti i membri del gruppo resteranno connessi."; +/* No comment provided by engineer. */ +"All messages will be deleted - this cannot be undone!" = "Tutti i messaggi verranno eliminati, non è reversibile!"; + /* No comment provided by engineer. */ "All messages will be deleted - this cannot be undone! The messages will be deleted ONLY for you." = "Tutti i messaggi verranno eliminati, non è reversibile! I messaggi verranno eliminati SOLO per te."; @@ -423,7 +426,7 @@ "Allow disappearing messages only if your contact allows it to you." = "Consenti i messaggi a tempo solo se il contatto li consente a te."; /* No comment provided by engineer. */ -"Allow irreversible message deletion only if your contact allows it to you." = "Consenti l'eliminazione irreversibile dei messaggi solo se il contatto la consente a te."; +"Allow irreversible message deletion only if your contact allows it to you. (24 hours)" = "Consenti l'eliminazione irreversibile dei messaggi solo se il contatto la consente a te. (24 ore)"; /* No comment provided by engineer. */ "Allow message reactions only if your contact allows them." = "Consenti reazioni ai messaggi solo se il tuo contatto le consente."; @@ -438,7 +441,7 @@ "Allow sending disappearing messages." = "Permetti l'invio di messaggi a tempo."; /* No comment provided by engineer. */ -"Allow to irreversibly delete sent messages." = "Permetti di eliminare irreversibilmente i messaggi inviati."; +"Allow to irreversibly delete sent messages. (24 hours)" = "Permetti di eliminare irreversibilmente i messaggi inviati. (24 ore)"; /* No comment provided by engineer. */ "Allow to send files and media." = "Consenti l'invio di file e contenuti multimediali."; @@ -459,7 +462,7 @@ "Allow your contacts to call you." = "Consenti ai tuoi contatti di chiamarti."; /* No comment provided by engineer. */ -"Allow your contacts to irreversibly delete sent messages." = "Permetti ai tuoi contatti di eliminare irreversibilmente i messaggi inviati."; +"Allow your contacts to irreversibly delete sent messages. (24 hours)" = "Permetti ai tuoi contatti di eliminare irreversibilmente i messaggi inviati. (24 ore)"; /* No comment provided by engineer. */ "Allow your contacts to send disappearing messages." = "Permetti ai tuoi contatti di inviare messaggi a tempo."; @@ -545,6 +548,9 @@ /* No comment provided by engineer. */ "Authentication unavailable" = "Autenticazione non disponibile"; +/* member role */ +"author" = "autore"; + /* No comment provided by engineer. */ "Auto-accept" = "Accetta automaticamente"; @@ -581,18 +587,33 @@ /* No comment provided by engineer. */ "Block" = "Blocca"; +/* No comment provided by engineer. */ +"Block for all" = "Blocca per tutti"; + /* No comment provided by engineer. */ "Block group members" = "Blocca i membri dei gruppi"; /* No comment provided by engineer. */ "Block member" = "Blocca membro"; +/* No comment provided by engineer. */ +"Block member for all?" = "Bloccare il membro per tutti?"; + /* No comment provided by engineer. */ "Block member?" = "Bloccare il membro?"; /* No comment provided by engineer. */ "blocked" = "bloccato"; +/* rcv group event chat item */ +"blocked %@" = "ha bloccato %@"; + +/* blocked chat item */ +"blocked by admin" = "bloccato dall'amministratore"; + +/* No comment provided by engineer. */ +"Blocked by admin" = "Bloccato dall'amministratore"; + /* No comment provided by engineer. */ "bold" = "grassetto"; @@ -600,7 +621,7 @@ "Both you and your contact can add message reactions." = "Sia tu che il tuo contatto potete aggiungere reazioni ai messaggi."; /* No comment provided by engineer. */ -"Both you and your contact can irreversibly delete sent messages." = "Sia tu che il tuo contatto potete eliminare irreversibilmente i messaggi inviati."; +"Both you and your contact can irreversibly delete sent messages. (24 hours)" = "Sia tu che il tuo contatto potete eliminare irreversibilmente i messaggi inviati. (24 ore)"; /* No comment provided by engineer. */ "Both you and your contact can make calls." = "Sia tu che il tuo contatto potete effettuare chiamate."; @@ -633,7 +654,7 @@ "Calls" = "Chiamate"; /* No comment provided by engineer. */ -"Can't delete user profile!" = "Impossibile eliminare il profilo utente!"; +"Camera not available" = "Fotocamera non disponibile"; /* No comment provided by engineer. */ "Can't invite contact!" = "Impossibile invitare il contatto!"; @@ -720,6 +741,9 @@ /* No comment provided by engineer. */ "Chat is stopped" = "Chat fermata"; +/* No comment provided by engineer. */ +"Chat is stopped. If you already used this database on another device, you should transfer it back before starting chat." = "La chat è ferma. Se hai già usato questo database su un altro dispositivo, dovresti trasferirlo prima di avviare la chat."; + /* No comment provided by engineer. */ "Chat preferences" = "Preferenze della chat"; @@ -747,6 +771,9 @@ /* No comment provided by engineer. */ "Clear conversation?" = "Svuotare la conversazione?"; +/* No comment provided by engineer. */ +"Clear private notes?" = "Svuotare le note private?"; + /* No comment provided by engineer. */ "Clear verification" = "Annulla la verifica"; @@ -775,7 +802,7 @@ "Confirm database upgrades" = "Conferma aggiornamenti database"; /* No comment provided by engineer. */ -"Confirm new passphrase…" = "Conferma password nuova…"; +"Confirm new passphrase…" = "Conferma nuova password…"; /* No comment provided by engineer. */ "Confirm Passcode" = "Conferma il codice di accesso"; @@ -786,6 +813,9 @@ /* server test step */ "Connect" = "Connetti"; +/* No comment provided by engineer. */ +"Connect automatically" = "Connetti automaticamente"; + /* No comment provided by engineer. */ "Connect incognito" = "Connetti in incognito"; @@ -810,9 +840,6 @@ /* No comment provided by engineer. */ "Connect via link" = "Connetti via link"; -/* No comment provided by engineer. */ -"Connect via link / QR code" = "Connetti via link / codice QR"; - /* No comment provided by engineer. */ "Connect via one-time link" = "Connetti via link una tantum"; @@ -885,6 +912,9 @@ /* connection information */ "connection:%@" = "connessione:% @"; +/* profile update event chat item */ +"contact %@ changed to %@" = "contatto %1$@ cambiato in %2$@"; + /* No comment provided by engineer. */ "Contact allows" = "Il contatto lo consente"; @@ -954,9 +984,6 @@ /* No comment provided by engineer. */ "Create new profile in [desktop app](https://simplex.chat/downloads/). 💻" = "Crea un nuovo profilo nell'[app desktop](https://simplex.chat/downloads/). 💻"; -/* No comment provided by engineer. */ -"Create one-time invitation link" = "Crea link di invito una tantum"; - /* No comment provided by engineer. */ "Create profile" = "Crea profilo"; @@ -972,9 +999,18 @@ /* No comment provided by engineer. */ "Create your profile" = "Crea il tuo profilo"; +/* No comment provided by engineer. */ +"Created at" = "Creato il"; + +/* copied message info */ +"Created at: %@" = "Creato il: %@"; + /* No comment provided by engineer. */ "Created on %@" = "Creato il %@"; +/* No comment provided by engineer. */ +"Creating link…" = "Creazione link…"; + /* No comment provided by engineer. */ "creator" = "creatore"; @@ -1287,9 +1323,15 @@ /* No comment provided by engineer. */ "Discover and join groups" = "Scopri ed unisciti ai gruppi"; +/* No comment provided by engineer. */ +"Discover via local network" = "Individua via rete locale"; + /* No comment provided by engineer. */ "Do it later" = "Fallo dopo"; +/* No comment provided by engineer. */ +"Do not send history to new members." = "Non inviare la cronologia ai nuovi membri."; + /* No comment provided by engineer. */ "Do NOT use SimpleX for emergency calls." = "NON usare SimpleX per chiamate di emergenza."; @@ -1335,6 +1377,9 @@ /* No comment provided by engineer. */ "Enable automatic message deletion?" = "Attivare l'eliminazione automatica dei messaggi?"; +/* No comment provided by engineer. */ +"Enable camera access" = "Attiva l'accesso alla fotocamera"; + /* No comment provided by engineer. */ "Enable for all" = "Attiva per tutti"; @@ -1389,6 +1434,9 @@ /* notification */ "Encrypted message or another event" = "Messaggio crittografato o altro evento"; +/* notification */ +"Encrypted message: app is stopped" = "Messaggio cifrato: l'app è ferma"; + /* notification */ "Encrypted message: database error" = "Messaggio crittografato: errore del database"; @@ -1509,6 +1557,9 @@ /* No comment provided by engineer. */ "Error creating member contact" = "Errore di creazione del contatto"; +/* No comment provided by engineer. */ +"Error creating message" = "Errore di creazione del messaggio"; + /* No comment provided by engineer. */ "Error creating profile!" = "Errore nella creazione del profilo!"; @@ -1560,6 +1611,9 @@ /* No comment provided by engineer. */ "Error loading %@ servers" = "Errore nel caricamento dei server %@"; +/* No comment provided by engineer. */ +"Error opening chat" = "Errore di apertura della chat"; + /* No comment provided by engineer. */ "Error receiving file" = "Errore nella ricezione del file"; @@ -1584,6 +1638,9 @@ /* No comment provided by engineer. */ "Error saving user password" = "Errore nel salvataggio della password utente"; +/* No comment provided by engineer. */ +"Error scanning code: %@" = "Errore di scansione del codice: %@"; + /* No comment provided by engineer. */ "Error sending email" = "Errore nell'invio dell'email"; @@ -1722,6 +1779,9 @@ /* No comment provided by engineer. */ "For console" = "Per console"; +/* No comment provided by engineer. */ +"Found desktop" = "Desktop trovato"; + /* No comment provided by engineer. */ "French interface" = "Interfaccia francese"; @@ -1786,7 +1846,7 @@ "Group members can add message reactions." = "I membri del gruppo possono aggiungere reazioni ai messaggi."; /* No comment provided by engineer. */ -"Group members can irreversibly delete sent messages." = "I membri del gruppo possono eliminare irreversibilmente i messaggi inviati."; +"Group members can irreversibly delete sent messages. (24 hours)" = "I membri del gruppo possono eliminare irreversibilmente i messaggi inviati. (24 ore)"; /* No comment provided by engineer. */ "Group members can send direct messages." = "I membri del gruppo possono inviare messaggi diretti."; @@ -1854,6 +1914,9 @@ /* No comment provided by engineer. */ "History" = "Cronologia"; +/* No comment provided by engineer. */ +"History is not sent to new members." = "La cronologia non viene inviata ai nuovi membri."; + /* time unit */ "hours" = "ore"; @@ -1878,9 +1941,6 @@ /* No comment provided by engineer. */ "If you can't meet in person, show QR code in a video call, or share the link." = "Se non potete incontrarvi di persona, mostra il codice QR in una videochiamata o condividi il link."; -/* No comment provided by engineer. */ -"If you cannot meet in person, you can **scan QR code in the video call**, or your contact can share an invitation link." = "Se non potete incontrarvi di persona, puoi **scansionare il codice QR durante la videochiamata** oppure il tuo contatto può condividere un link di invito."; - /* No comment provided by engineer. */ "If you enter this passcode when opening the app, all app data will be irreversibly removed!" = "Se inserisci questo codice all'apertura dell'app, tutti i dati di essa verranno rimossi in modo irreversibile!"; @@ -1914,6 +1974,9 @@ /* No comment provided by engineer. */ "Import database" = "Importa database"; +/* No comment provided by engineer. */ +"Improved message delivery" = "Consegna dei messaggi migliorata"; + /* No comment provided by engineer. */ "Improved privacy and security" = "Privacy e sicurezza migliorate"; @@ -1998,9 +2061,21 @@ /* invalid chat item */ "invalid data" = "dati non validi"; +/* No comment provided by engineer. */ +"Invalid display name!" = "Nome da mostrare non valido!"; + +/* No comment provided by engineer. */ +"Invalid link" = "Link non valido"; + /* No comment provided by engineer. */ "Invalid name!" = "Nome non valido!"; +/* No comment provided by engineer. */ +"Invalid QR code" = "Codice QR non valido"; + +/* No comment provided by engineer. */ +"Invalid response" = "Risposta non valida"; + /* No comment provided by engineer. */ "Invalid server address!" = "Indirizzo del server non valido!"; @@ -2079,6 +2154,9 @@ /* No comment provided by engineer. */ "Join group" = "Entra nel gruppo"; +/* No comment provided by engineer. */ +"Join group conversations" = "Entra in conversazioni di gruppo"; + /* No comment provided by engineer. */ "Join group?" = "Entrare nel gruppo?"; @@ -2094,9 +2172,15 @@ /* No comment provided by engineer. */ "Joining group" = "Ingresso nel gruppo"; +/* No comment provided by engineer. */ +"Keep" = "Tieni"; + /* No comment provided by engineer. */ "Keep the app open to use it from desktop" = "Tieni aperta l'app per usarla dal desktop"; +/* No comment provided by engineer. */ +"Keep unused invitation?" = "Tenere l'invito inutilizzato?"; + /* No comment provided by engineer. */ "Keep your connections" = "Mantieni le tue connessioni"; @@ -2151,6 +2235,9 @@ /* No comment provided by engineer. */ "Live messages" = "Messaggi in diretta"; +/* No comment provided by engineer. */ +"Local" = "Locale"; + /* No comment provided by engineer. */ "Local name" = "Nome locale"; @@ -2205,6 +2292,9 @@ /* No comment provided by engineer. */ "Member" = "Membro"; +/* profile update event chat item */ +"member %@ changed to %@" = "membro %1$@ cambiato in %2$@"; + /* rcv group event chat item */ "member connected" = "si è connesso/a"; @@ -2322,6 +2412,9 @@ /* No comment provided by engineer. */ "never" = "mai"; +/* No comment provided by engineer. */ +"New chat" = "Nuova chat"; + /* notification */ "New contact request" = "Nuova richiesta di contatto"; @@ -2397,6 +2490,9 @@ /* copied message info in history */ "no text" = "nessun testo"; +/* No comment provided by engineer. */ +"Not compatible!" = "Non compatibile!"; + /* No comment provided by engineer. */ "Notifications" = "Notifiche"; @@ -2417,9 +2513,6 @@ /* No comment provided by engineer. */ "Off" = "Off"; -/* No comment provided by engineer. */ -"Off (Local)" = "Off (Locale)"; - /* feature offered item */ "offered %@" = "offerto %@"; @@ -2429,6 +2522,9 @@ /* No comment provided by engineer. */ "Ok" = "Ok"; +/* No comment provided by engineer. */ +"OK" = "OK"; + /* No comment provided by engineer. */ "Old database" = "Database vecchio"; @@ -2466,7 +2562,7 @@ "Only you can add message reactions." = "Solo tu puoi aggiungere reazioni ai messaggi."; /* No comment provided by engineer. */ -"Only you can irreversibly delete messages (your contact can mark them for deletion)." = "Solo tu puoi eliminare irreversibilmente i messaggi (il tuo contatto può contrassegnarli per l'eliminazione)."; +"Only you can irreversibly delete messages (your contact can mark them for deletion). (24 hours)" = "Solo tu puoi eliminare irreversibilmente i messaggi (il tuo contatto può contrassegnarli per l'eliminazione). (24 ore)"; /* No comment provided by engineer. */ "Only you can make calls." = "Solo tu puoi effettuare chiamate."; @@ -2481,7 +2577,7 @@ "Only your contact can add message reactions." = "Solo il tuo contatto può aggiungere reazioni ai messaggi."; /* No comment provided by engineer. */ -"Only your contact can irreversibly delete messages (you can mark them for deletion)." = "Solo il tuo contatto può eliminare irreversibilmente i messaggi (tu puoi contrassegnarli per l'eliminazione)."; +"Only your contact can irreversibly delete messages (you can mark them for deletion). (24 hours)" = "Solo il tuo contatto può eliminare irreversibilmente i messaggi (tu puoi contrassegnarli per l'eliminazione). (24 ore)"; /* No comment provided by engineer. */ "Only your contact can make calls." = "Solo il tuo contatto può effettuare chiamate."; @@ -2514,7 +2610,13 @@ "Open-source protocol and code – anybody can run the servers." = "Protocollo e codice open source: chiunque può gestire i server."; /* No comment provided by engineer. */ -"Opening database…" = "Apertura del database…"; +"Opening app…" = "Apertura dell'app…"; + +/* No comment provided by engineer. */ +"Or scan QR code" = "O scansiona il codice QR"; + +/* No comment provided by engineer. */ +"Or show this code" = "O mostra questo codice"; /* member role */ "owner" = "proprietario"; @@ -2537,8 +2639,8 @@ /* No comment provided by engineer. */ "Password to show" = "Password per mostrare"; -/* No comment provided by engineer. */ -"Paste" = "Incolla"; +/* past/unknown group member */ +"Past member %@" = "Membro passato %@"; /* No comment provided by engineer. */ "Paste desktop address" = "Incolla l'indirizzo desktop"; @@ -2547,10 +2649,10 @@ "Paste image" = "Incolla immagine"; /* No comment provided by engineer. */ -"Paste received link" = "Incolla il link ricevuto"; +"Paste link to connect!" = "Incolla un link per connettere!"; -/* placeholder */ -"Paste the link you received to connect with your contact." = "Incolla il link che hai ricevuto nella casella sottostante per connetterti con il tuo contatto."; +/* No comment provided by engineer. */ +"Paste the link you received" = "Incolla il link che hai ricevuto"; /* No comment provided by engineer. */ "peer-to-peer" = "peer-to-peer"; @@ -2582,6 +2684,9 @@ /* No comment provided by engineer. */ "Please check yours and your contact preferences." = "Controlla le preferenze tue e del tuo contatto."; +/* No comment provided by engineer. */ +"Please contact developers.\nError: %@" = "Contatta gli sviluppatori.\nErrore: %@"; + /* No comment provided by engineer. */ "Please contact group admin." = "Contatta l'amministratore del gruppo."; @@ -2633,6 +2738,9 @@ /* No comment provided by engineer. */ "Private filenames" = "Nomi di file privati"; +/* name of notes to self */ +"Private notes" = "Note private"; + /* No comment provided by engineer. */ "Profile and server connections" = "Profilo e connessioni al server"; @@ -2705,6 +2813,9 @@ /* No comment provided by engineer. */ "Read more in [User Guide](https://simplex.chat/docs/guide/app-settings.html#your-simplex-contact-address)." = "Maggiori informazioni nella [Guida per l'utente](https://simplex.chat/docs/guide/app-settings.html#your-simplex-contact-address)."; +/* No comment provided by engineer. */ +"Read more in [User Guide](https://simplex.chat/docs/guide/chat-profiles.html#incognito-mode)." = "Leggi di più nella [Guida utente](https://simplex.chat/docs/guide/chat-profiles.html#incognito-mode)."; + /* No comment provided by engineer. */ "Read more in [User Guide](https://simplex.chat/docs/guide/readme.html#connect-to-friends)." = "Maggiori informazioni nella [Guida per l'utente](https://simplex.chat/docs/guide/readme.html#connect-to-friends)."; @@ -2744,6 +2855,9 @@ /* No comment provided by engineer. */ "Receiving via" = "Ricezione via"; +/* No comment provided by engineer. */ +"Recent history and improved [directory bot](simplex:/contact#/?v=1-4&smp=smp%3A%2F%2Fu2dS9sG8nMNURyZwqASV4yROM28Er0luVTx5X1CsMrU%3D%40smp4.simplex.im%2FeXSPwqTkKyDO3px4fLf1wx3MvPdjdLW3%23%2F%3Fv%3D1-2%26dh%3DMCowBQYDK2VuAyEAaiv6MkMH44L2TcYrt_CsX3ZvM11WgbMEUn0hkIKTOho%253D%26srv%3Do5vmywmrnaxalvz6wi3zicyftgio6psuvyniis6gco6bp6ekl4cqj4id.onion)." = "Cronologia recente e [bot della directory](simplex:/contact#/?v=1-4&smp=smp%3A%2F%2Fu2dS9sG8nMNURyZwqASV4yROM28Er0luVTx5X1CsMrU%3D%40smp4.simplex.im%2FeXSPwqTkKyDO3px4fLf1wx3MvPdjdLW3%23%2F%3Fv%3D1-2%26dh%3DMCowBQYDK2VuAyEAaiv6MkMH44L2TcYrt_CsX3ZvM11WgbMEUn0hkIKTOho%253D%26srv%3Do5vmywmrnaxalvz6wi3zicyftgio6psuvyniis6gco6bp6ekl4cqj4id.onion) migliorato."; + /* No comment provided by engineer. */ "Recipients see updates as you type them." = "I destinatari vedono gli aggiornamenti mentre li digiti."; @@ -2798,6 +2912,12 @@ /* rcv group event chat item */ "removed %@" = "ha rimosso %@"; +/* profile update event chat item */ +"removed contact address" = "indirizzo di contatto rimosso"; + +/* profile update event chat item */ +"removed profile picture" = "immagine del profilo rimossa"; + /* rcv group event chat item */ "removed you" = "ti ha rimosso/a"; @@ -2849,6 +2969,9 @@ /* No comment provided by engineer. */ "Restore database error" = "Errore di ripristino del database"; +/* No comment provided by engineer. */ +"Retry" = "Riprova"; + /* chat item action */ "Reveal" = "Rivela"; @@ -2918,6 +3041,9 @@ /* No comment provided by engineer. */ "Save welcome message?" = "Salvare il messaggio di benvenuto?"; +/* message info title */ +"Saved message" = "Messaggio salvato"; + /* No comment provided by engineer. */ "Saved WebRTC ICE servers will be removed" = "I server WebRTC ICE salvati verranno rimossi"; @@ -2939,6 +3065,12 @@ /* No comment provided by engineer. */ "Search" = "Cerca"; +/* No comment provided by engineer. */ +"Search bar accepts invitation links." = "La barra di ricerca accetta i link di invito."; + +/* No comment provided by engineer. */ +"Search or paste SimpleX link" = "Cerca o incolla un link SimpleX"; + /* network option */ "sec" = "sec"; @@ -3017,6 +3149,9 @@ /* No comment provided by engineer. */ "Send them from gallery or custom keyboards." = "Inviali dalla galleria o dalle tastiere personalizzate."; +/* No comment provided by engineer. */ +"Send up to 100 last messages to new members." = "Invia fino a 100 ultimi messaggi ai nuovi membri."; + /* No comment provided by engineer. */ "Sender cancelled file transfer." = "Il mittente ha annullato il trasferimento del file."; @@ -3089,6 +3224,12 @@ /* No comment provided by engineer. */ "Set it instead of system authentication." = "Impostalo al posto dell'autenticazione di sistema."; +/* profile update event chat item */ +"set new contact address" = "impostato nuovo indirizzo di contatto"; + +/* profile update event chat item */ +"set new profile picture" = "impostata nuova immagine del profilo"; + /* No comment provided by engineer. */ "Set passcode" = "Imposta codice"; @@ -3120,7 +3261,7 @@ "Share link" = "Condividi link"; /* No comment provided by engineer. */ -"Share one-time invitation link" = "Condividi link di invito una tantum"; +"Share this 1-time invite link" = "Condividi questo link di invito una tantum"; /* No comment provided by engineer. */ "Share with contacts" = "Condividi con i contatti"; @@ -3150,7 +3291,7 @@ "SimpleX Chat security was audited by Trail of Bits." = "La sicurezza di SimpleX Chat è stata verificata da Trail of Bits."; /* simplex link type */ -"SimpleX contact address" = "Indirizzo del contatto SimpleX"; +"SimpleX contact address" = "Indirizzo di contatto SimpleX"; /* notification */ "SimpleX encrypted message or connection event" = "Messaggio crittografato di SimpleX o evento di connessione"; @@ -3198,10 +3339,10 @@ "Somebody" = "Qualcuno"; /* No comment provided by engineer. */ -"Start a new chat" = "Inizia una nuova chat"; +"Start chat" = "Avvia chat"; /* No comment provided by engineer. */ -"Start chat" = "Avvia chat"; +"Start chat?" = "Avviare la chat?"; /* No comment provided by engineer. */ "Start migration" = "Avvia la migrazione"; @@ -3272,6 +3413,12 @@ /* No comment provided by engineer. */ "Tap to join incognito" = "Toccare per entrare in incognito"; +/* No comment provided by engineer. */ +"Tap to paste link" = "Tocca per incollare il link"; + +/* No comment provided by engineer. */ +"Tap to scan" = "Tocca per scansionare"; + /* No comment provided by engineer. */ "Tap to start a new chat" = "Tocca per iniziare una chat"; @@ -3317,6 +3464,9 @@ /* No comment provided by engineer. */ "The attempt to change database passphrase was not completed." = "Il tentativo di cambiare la password del database non è stato completato."; +/* No comment provided by engineer. */ +"The code you scanned is not a SimpleX link QR code." = "Il codice che hai scansionato non è un codice QR di link SimpleX."; + /* No comment provided by engineer. */ "The connection you accepted will be cancelled!" = "La connessione che hai accettato verrà annullata!"; @@ -3359,15 +3509,12 @@ /* No comment provided by engineer. */ "The servers for new connections of your current chat profile **%@**." = "I server per le nuove connessioni del profilo di chat attuale **%@**."; +/* No comment provided by engineer. */ +"The text you pasted is not a SimpleX link." = "Il testo che hai incollato non è un link SimpleX."; + /* No comment provided by engineer. */ "Theme" = "Tema"; -/* No comment provided by engineer. */ -"There should be at least one user profile." = "Deve esserci almeno un profilo utente."; - -/* No comment provided by engineer. */ -"There should be at least one visible user profile." = "Deve esserci almeno un profilo utente visibile."; - /* No comment provided by engineer. */ "These settings are for your current profile **%@**." = "Queste impostazioni sono per il tuo profilo attuale **%@**."; @@ -3389,6 +3536,9 @@ /* No comment provided by engineer. */ "This device name" = "Il nome di questo dispositivo"; +/* No comment provided by engineer. */ +"This display name is invalid. Please choose another name." = "Questo nome da mostrare non è valido. Scegline un altro."; + /* No comment provided by engineer. */ "This group has over %lld members, delivery receipts are not sent." = "Questo gruppo ha più di %lld membri, le ricevute di consegna non vengono inviate."; @@ -3450,10 +3600,10 @@ "Trying to connect to the server used to receive messages from this contact." = "Tentativo di connessione al server usato per ricevere messaggi da questo contatto."; /* No comment provided by engineer. */ -"Turn off" = "Spegni"; +"Turkish interface" = "Interfaccia in turco"; /* No comment provided by engineer. */ -"Turn off notifications?" = "Spegnere le notifiche?"; +"Turn off" = "Spegni"; /* No comment provided by engineer. */ "Turn on" = "Attiva"; @@ -3464,12 +3614,21 @@ /* No comment provided by engineer. */ "Unblock" = "Sblocca"; +/* No comment provided by engineer. */ +"Unblock for all" = "Sblocca per tutti"; + /* No comment provided by engineer. */ "Unblock member" = "Sblocca membro"; +/* No comment provided by engineer. */ +"Unblock member for all?" = "Sbloccare il membro per tutti?"; + /* No comment provided by engineer. */ "Unblock member?" = "Sbloccare il membro?"; +/* rcv group event chat item */ +"unblocked %@" = "ha sbloccato %@"; + /* item status description */ "Unexpected error: %@" = "Errore imprevisto: % @"; @@ -3503,6 +3662,9 @@ /* No comment provided by engineer. */ "Unknown error" = "Errore sconosciuto"; +/* No comment provided by engineer. */ +"unknown status" = "stato sconosciuto"; + /* No comment provided by engineer. */ "Unless you use iOS call interface, enable Do Not Disturb mode to avoid interruptions." = "A meno che non utilizzi l'interfaccia di chiamata iOS, attiva la modalità Non disturbare per evitare interruzioni."; @@ -3527,6 +3689,9 @@ /* No comment provided by engineer. */ "Unread" = "Non letto"; +/* No comment provided by engineer. */ +"Up to 100 last messages are sent to new members." = "Vengono inviati ai nuovi membri fino a 100 ultimi messaggi."; + /* No comment provided by engineer. */ "Update" = "Aggiorna"; @@ -3543,7 +3708,10 @@ "Update transport isolation mode?" = "Aggiornare la modalità di isolamento del trasporto?"; /* rcv group event chat item */ -"updated group profile" = "profilo del gruppo aggiornato"; +"updated group profile" = "ha aggiornato il profilo del gruppo"; + +/* profile update event chat item */ +"updated profile" = "profilo aggiornato"; /* No comment provided by engineer. */ "Updating settings will re-connect the client to all servers." = "L'aggiornamento delle impostazioni riconnetterà il client a tutti i server."; @@ -3578,6 +3746,9 @@ /* No comment provided by engineer. */ "Use new incognito profile" = "Usa nuovo profilo in incognito"; +/* No comment provided by engineer. */ +"Use only local notifications?" = "Usare solo notifiche locali?"; + /* No comment provided by engineer. */ "Use server" = "Usa il server"; @@ -3650,6 +3821,9 @@ /* No comment provided by engineer. */ "View security code" = "Vedi codice di sicurezza"; +/* chat feature */ +"Visible history" = "Cronologia visibile"; + /* No comment provided by engineer. */ "Voice message…" = "Messaggio vocale…"; @@ -3671,6 +3845,9 @@ /* No comment provided by engineer. */ "waiting for confirmation…" = "in attesa di conferma…"; +/* No comment provided by engineer. */ +"Waiting for desktop..." = "In attesa del desktop..."; + /* No comment provided by engineer. */ "Waiting for file" = "In attesa del file"; @@ -3710,9 +3887,15 @@ /* No comment provided by engineer. */ "When you share an incognito profile with somebody, this profile will be used for the groups they invite you to." = "Quando condividi un profilo in incognito con qualcuno, questo profilo verrà utilizzato per i gruppi a cui ti invitano."; +/* No comment provided by engineer. */ +"With encrypted files and media." = "Con file e multimediali criptati."; + /* No comment provided by engineer. */ "With optional welcome message." = "Con messaggio di benvenuto facoltativo."; +/* No comment provided by engineer. */ +"With reduced battery usage." = "Con consumo di batteria ridotto."; + /* No comment provided by engineer. */ "Wrong database passphrase" = "Password del database sbagliata"; @@ -3773,11 +3956,11 @@ /* No comment provided by engineer. */ "you are observer" = "sei un osservatore"; -/* No comment provided by engineer. */ -"You can accept calls from lock screen, without device and app authentication." = "Puoi accettare chiamate dalla schermata di blocco, senza l'autenticazione del dispositivo e dell'app."; +/* snd group event chat item */ +"you blocked %@" = "hai bloccato %@"; /* No comment provided by engineer. */ -"You can also connect by clicking the link. If it opens in the browser, click **Open in mobile app** button." = "Puoi anche connetterti cliccando il link. Se si apre nel browser, clicca il pulsante **Apri nell'app mobile**."; +"You can accept calls from lock screen, without device and app authentication." = "Puoi accettare chiamate dalla schermata di blocco, senza l'autenticazione del dispositivo e dell'app."; /* No comment provided by engineer. */ "You can create it later" = "Puoi crearlo più tardi"; @@ -3791,6 +3974,9 @@ /* No comment provided by engineer. */ "You can hide or mute a user profile - swipe it to the right." = "Puoi nascondere o silenziare un profilo utente - scorrilo verso destra."; +/* No comment provided by engineer. */ +"You can make it visible to your SimpleX contacts via Settings." = "Puoi renderlo visibile ai tuoi contatti SimpleX nelle impostazioni."; + /* notification body */ "You can now send messages to %@" = "Ora puoi inviare messaggi a %@"; @@ -3815,6 +4001,9 @@ /* No comment provided by engineer. */ "You can use markdown to format messages:" = "Puoi usare il markdown per formattare i messaggi:"; +/* No comment provided by engineer. */ +"You can view invitation link again in connection details." = "Puoi vedere di nuovo il link di invito nei dettagli di connessione."; + /* No comment provided by engineer. */ "You can't send messages!" = "Non puoi inviare messaggi!"; @@ -3831,7 +4020,7 @@ "you changed role of %@ to %@" = "hai cambiato il ruolo di %1$@ in %2$@"; /* No comment provided by engineer. */ -"You control through which server(s) **to receive** the messages, your contacts – the servers you use to message them." = "Puoi controllare attraverso quale/i server **ricevere** i messaggi, i tuoi contatti – i server che usi per inviare loro i messaggi."; +"You control through which server(s) **to receive** the messages, your contacts – the servers you use to message them." = "Tu decidi attraverso quale/i server **ricevere** i messaggi, i tuoi contatti quali server usi per inviare loro i messaggi."; /* No comment provided by engineer. */ "You could not be verified; please try again." = "Non è stato possibile verificarti, riprova."; @@ -3881,6 +4070,9 @@ /* chat list item description */ "you shared one-time link incognito" = "hai condiviso un link incognito una tantum"; +/* snd group event chat item */ +"you unblocked %@" = "hai sbloccato %@"; + /* No comment provided by engineer. */ "You will be connected to group when the group host's device is online, please wait or check later!" = "Verrai connesso/a al gruppo quando il dispositivo dell'host del gruppo sarà in linea, attendi o controlla più tardi!"; @@ -3941,9 +4133,6 @@ /* No comment provided by engineer. */ "Your contacts can allow full message deletion." = "I tuoi contatti possono consentire l'eliminazione completa dei messaggi."; -/* No comment provided by engineer. */ -"Your contacts in SimpleX will see it.\nYou can change it in Settings." = "I tuoi contatti in SimpleX lo vedranno.\nPuoi modificarlo nelle impostazioni."; - /* No comment provided by engineer. */ "Your contacts will remain connected." = "I tuoi contatti resteranno connessi."; diff --git a/apps/ios/ja.lproj/Localizable.strings b/apps/ios/ja.lproj/Localizable.strings index ff97d71daf..fb11e89959 100644 --- a/apps/ios/ja.lproj/Localizable.strings +++ b/apps/ios/ja.lproj/Localizable.strings @@ -56,13 +56,10 @@ "**Add new contact**: to create your one-time QR Code for your contact." = "**新しい連絡先を追加**: 連絡先のワンタイム QR コードまたはリンクを作成します。"; /* No comment provided by engineer. */ -"**Create link / QR code** for your contact to use." = "連絡先が使用する **リンク/QR コードを作成します**。"; +"**e2e encrypted** audio call" = "**e2e 暗号化**音声通話"; /* No comment provided by engineer. */ -"**e2e encrypted** audio call" = "**e2e 暗号化**された音声通話"; - -/* No comment provided by engineer. */ -"**e2e encrypted** video call" = "**エンドツーエンド暗号化済み**のビデオ通話"; +"**e2e encrypted** video call" = "**e2e暗号化**ビデオ通話"; /* No comment provided by engineer. */ "**More private**: check new messages every 20 minutes. Device token is shared with SimpleX Chat server, but not how many contacts or messages you have." = "**よりプライベート**: 20 分ごとに新しいメッセージを確認します。 デバイス トークンは SimpleX Chat サーバーと共有されますが、連絡先やメッセージの数は共有されません。"; @@ -70,23 +67,17 @@ /* No comment provided by engineer. */ "**Most private**: do not use SimpleX Chat notifications server, check messages periodically in the background (depends on how often you use the app)." = "**最もプライベート**: SimpleX Chat 通知サーバーを使用せず、バックグラウンドで定期的にメッセージをチェックします (アプリの使用頻度によって異なります)。"; -/* No comment provided by engineer. */ -"**Paste received link** or open it in the browser and tap **Open in mobile app**." = "**受信したリンク**を貼り付けるか、ブラウザーで開いて [**モバイル アプリで開く**] をタップします。"; - /* No comment provided by engineer. */ "**Please note**: you will NOT be able to recover or change passphrase if you lose it." = "**注意**: パスフレーズを紛失すると、パスフレーズを復元または変更できなくなります。"; /* No comment provided by engineer. */ "**Recommended**: device token and notifications are sent to SimpleX Chat notification server, but not the message content, size or who it is from." = "**推奨**: デバイス トークンと通知は SimpleX Chat 通知サーバーに送信されますが、メッセージの内容、サイズ、送信者は送信されません。"; -/* No comment provided by engineer. */ -"**Scan QR code**: to connect to your contact in person or via video call." = "**QR コードをスキャン**: 直接またはビデオ通話で連絡先に接続します。"; - /* No comment provided by engineer. */ "**Warning**: Instant push notifications require passphrase saved in Keychain." = "**警告**: 即時の プッシュ通知には、キーチェーンに保存されたパスフレーズが必要です。"; /* No comment provided by engineer. */ -"*bold*" = "\\*太文字*"; +"*bold*" = "\\*太字*"; /* copied message info title, # <title> */ "# %@" = "# %@"; @@ -121,6 +112,9 @@ /* copied message info, <sender> at <time> */ "%@ at %@:" = "%1$@ at %2$@:"; +/* No comment provided by engineer. */ +"%@ connected" = "%@ 接続中"; + /* notification title */ "%@ is connected!" = "%@ 接続中!"; @@ -178,6 +172,12 @@ /* No comment provided by engineer. */ "%lld members" = "%lld 人のメンバー"; +/* No comment provided by engineer. */ +"%lld messages marked deleted" = "%lld 件のメッセージが削除されました"; + +/* No comment provided by engineer. */ +"%lld messages moderated by %@" = "%@ により%lld 件のメッセージが検閲されました"; + /* No comment provided by engineer. */ "%lld minutes" = "%lld 分"; @@ -244,9 +244,6 @@ /* time interval */ "1 week" = "1週間"; -/* No comment provided by engineer. */ -"1-time link" = "使い捨てのリンク"; - /* No comment provided by engineer. */ "5 minutes" = "5分"; @@ -300,7 +297,7 @@ "Accept" = "承諾"; /* No comment provided by engineer. */ -"Accept connection request?" = "連絡を受け入れる"; +"Accept connection request?" = "接続要求を承認?"; /* notification body */ "Accept contact request from %@?" = "%@ からの連絡要求を受け入れますか?"; @@ -372,7 +369,7 @@ "All your contacts will remain connected." = "あなたの連絡先が繋がったまま継続します。"; /* No comment provided by engineer. */ -"All your contacts will remain connected. Profile update will be sent to your contacts." = "あなたの連絡先が繋がったまま継続します。"; +"All your contacts will remain connected. Profile update will be sent to your contacts." = "すべての連絡先は維持されます。連絡先に更新されたプロフィールを送信します。"; /* No comment provided by engineer. */ "Allow" = "許可"; @@ -384,7 +381,7 @@ "Allow disappearing messages only if your contact allows it to you." = "連絡先が許可している場合のみ消えるメッセージを許可する。"; /* No comment provided by engineer. */ -"Allow irreversible message deletion only if your contact allows it to you." = "送信相手も永久メッセージ削除を許可する時のみに許可する。"; +"Allow irreversible message deletion only if your contact allows it to you. (24 hours)" = "送信相手も永久メッセージ削除を許可する時のみに許可する。"; /* No comment provided by engineer. */ "Allow message reactions only if your contact allows them." = "連絡先が許可している場合にのみ、メッセージへのリアクションを許可します。"; @@ -399,7 +396,7 @@ "Allow sending disappearing messages." = "消えるメッセージの送信を許可する。"; /* No comment provided by engineer. */ -"Allow to irreversibly delete sent messages." = "送信済みメッセージの永久削除を許可する。"; +"Allow to irreversibly delete sent messages. (24 hours)" = "送信済みメッセージの永久削除を許可する。"; /* No comment provided by engineer. */ "Allow to send files and media." = "ファイルやメディアの送信を許可する。"; @@ -420,7 +417,7 @@ "Allow your contacts to call you." = "連絡先からの通話を許可する。"; /* No comment provided by engineer. */ -"Allow your contacts to irreversibly delete sent messages." = "送信相手が永久メッセージ削除するのを許可する。"; +"Allow your contacts to irreversibly delete sent messages. (24 hours)" = "送信相手が永久メッセージ削除するのを許可する。"; /* No comment provided by engineer. */ "Allow your contacts to send disappearing messages." = "送信相手が消えるメッセージを送るのを許可する。"; @@ -531,7 +528,7 @@ "Both you and your contact can add message reactions." = "自分も相手もメッセージへのリアクションを追加できます。"; /* No comment provided by engineer. */ -"Both you and your contact can irreversibly delete sent messages." = "あなたと連絡相手が送信済みメッセージを永久削除できます。"; +"Both you and your contact can irreversibly delete sent messages. (24 hours)" = "あなたと連絡相手が送信済みメッセージを永久削除できます。"; /* No comment provided by engineer. */ "Both you and your contact can make calls." = "あなたからも連絡先からも通話ができます。"; @@ -563,9 +560,6 @@ /* No comment provided by engineer. */ "Calls" = "通話"; -/* No comment provided by engineer. */ -"Can't delete user profile!" = "ユーザープロフィールが削除できません!"; - /* No comment provided by engineer. */ "Can't invite contact!" = "連絡先を招待できません!"; @@ -727,10 +721,7 @@ "Connect via link" = "リンク経由で接続"; /* No comment provided by engineer. */ -"Connect via link / QR code" = "リンク・QRコード経由で接続"; - -/* No comment provided by engineer. */ -"Connect via one-time link" = "使い捨てリンク経由で接続しますか?"; +"Connect via one-time link" = "ワンタイムリンクで接続"; /* No comment provided by engineer. */ "connected" = "接続中"; @@ -843,9 +834,6 @@ /* No comment provided by engineer. */ "Create new profile in [desktop app](https://simplex.chat/downloads/). 💻" = "[デスクトップアプリ](https://simplex.chat/downloads/)で新しいプロファイルを作成します。 💻"; -/* No comment provided by engineer. */ -"Create one-time invitation link" = "使い捨ての招待リンクを生成する"; - /* server test step */ "Create queue" = "キューの作成"; @@ -1072,10 +1060,10 @@ "deleted group" = "削除されたグループ"; /* No comment provided by engineer. */ -"Delivery" = "Delivery"; +"Delivery" = "配信"; /* No comment provided by engineer. */ -"Delivery receipts are disabled!" = "Delivery receipts are disabled!"; +"Delivery receipts are disabled!" = "配信通知の停止!"; /* No comment provided by engineer. */ "Delivery receipts!" = "配信通知!"; @@ -1612,7 +1600,7 @@ "Group members can add message reactions." = "グループメンバーはメッセージへのリアクションを追加できます。"; /* No comment provided by engineer. */ -"Group members can irreversibly delete sent messages." = "グループのメンバーがメッセージを完全削除することができます。"; +"Group members can irreversibly delete sent messages. (24 hours)" = "グループのメンバーがメッセージを完全削除することができます。"; /* No comment provided by engineer. */ "Group members can send direct messages." = "グループのメンバーがダイレクトメッセージを送信できます。"; @@ -1704,9 +1692,6 @@ /* No comment provided by engineer. */ "If you can't meet in person, show QR code in a video call, or share the link." = "直接会えない場合は、ビデオ通話で QR コードを表示するか、リンクを共有してください。"; -/* No comment provided by engineer. */ -"If you cannot meet in person, you can **scan QR code in the video call**, or your contact can share an invitation link." = "直接会えない場合は、**ビデオ通話で QR コードを表示する**か、リンクを共有してください。"; - /* No comment provided by engineer. */ "If you enter this passcode when opening the app, all app data will be irreversibly removed!" = "アプリを開くときにこのパスコードを入力すると、アプリのすべてのデータが元に戻せないように削除されます!"; @@ -1947,6 +1932,9 @@ /* No comment provided by engineer. */ "Live messages" = "ライブメッセージ"; +/* No comment provided by engineer. */ +"Local" = "自分のみ"; + /* No comment provided by engineer. */ "Local name" = "ローカルネーム"; @@ -2207,9 +2195,6 @@ /* No comment provided by engineer. */ "Off" = "オフ"; -/* No comment provided by engineer. */ -"Off (Local)" = "オフ(自分のみ)"; - /* feature offered item */ "offered %@" = "提供された %@"; @@ -2256,7 +2241,7 @@ "Only you can add message reactions." = "メッセージへのリアクションを追加できるのは、あなただけです。"; /* No comment provided by engineer. */ -"Only you can irreversibly delete messages (your contact can mark them for deletion)." = "メッセージの完全削除はあなたにしかできません (あなたの連絡先は削除対象とすることができます)。"; +"Only you can irreversibly delete messages (your contact can mark them for deletion). (24 hours)" = "メッセージの完全削除はあなたにしかできません (あなたの連絡先は削除対象とすることができます)。"; /* No comment provided by engineer. */ "Only you can make calls." = "自分からのみ通話ができます。"; @@ -2271,7 +2256,7 @@ "Only your contact can add message reactions." = "メッセージへのリアクションを追加できるのは連絡先だけです。"; /* No comment provided by engineer. */ -"Only your contact can irreversibly delete messages (you can mark them for deletion)." = "メッセージを完全削除できるのはあなたの連絡相手だけです (あなたは削除対象とすることができます)。"; +"Only your contact can irreversibly delete messages (you can mark them for deletion). (24 hours)" = "メッセージを完全削除できるのはあなたの連絡相手だけです (あなたは削除対象とすることができます)。"; /* No comment provided by engineer. */ "Only your contact can make calls." = "連絡先からのみ通話ができます。"; @@ -2300,9 +2285,6 @@ /* No comment provided by engineer. */ "Open-source protocol and code – anybody can run the servers." = "プロトコル技術とコードはオープンソースで、どなたでもご自分のサーバを運用できます。"; -/* No comment provided by engineer. */ -"Opening database…" = "データベースを開いています…"; - /* member role */ "owner" = "オーナー"; @@ -2324,18 +2306,9 @@ /* No comment provided by engineer. */ "Password to show" = "パスワードを表示する"; -/* No comment provided by engineer. */ -"Paste" = "貼り付け"; - /* No comment provided by engineer. */ "Paste image" = "画像の貼り付け"; -/* No comment provided by engineer. */ -"Paste received link" = "頂いたリンクを貼り付ける"; - -/* placeholder */ -"Paste the link you received to connect with your contact." = "連絡相手から頂いたリンクを以下の入力欄に貼り付けて繋がります。"; - /* No comment provided by engineer. */ "peer-to-peer" = "P2P"; @@ -2855,9 +2828,6 @@ /* No comment provided by engineer. */ "Share link" = "リンクを送る"; -/* No comment provided by engineer. */ -"Share one-time invitation link" = "使い捨ての招待リンクを共有"; - /* No comment provided by engineer. */ "Share with contacts" = "連絡先と共有する"; @@ -2933,9 +2903,6 @@ /* notification title */ "Somebody" = "誰か"; -/* No comment provided by engineer. */ -"Start a new chat" = "新しいチャットを開始する"; - /* No comment provided by engineer. */ "Start chat" = "チャットを開始する"; @@ -3095,12 +3062,6 @@ /* No comment provided by engineer. */ "Theme" = "テーマ"; -/* No comment provided by engineer. */ -"There should be at least one user profile." = "少なくとも1つのユーザープロファイルが必要です。"; - -/* No comment provided by engineer. */ -"There should be at least one visible user profile." = "少なくとも1つのユーザープロフィールが表示されている必要があります。"; - /* No comment provided by engineer. */ "These settings are for your current profile **%@**." = "これらの設定は現在のプロファイル **%@** 用です。"; @@ -3167,9 +3128,6 @@ /* No comment provided by engineer. */ "Turn off" = "オフにする"; -/* No comment provided by engineer. */ -"Turn off notifications?" = "通知をオフにしますか?"; - /* No comment provided by engineer. */ "Turn on" = "オンにする"; @@ -3437,9 +3395,6 @@ /* No comment provided by engineer. */ "You can accept calls from lock screen, without device and app authentication." = "デバイスやアプリの認証を行わずに、ロック画面から通話を受けることができます。"; -/* No comment provided by engineer. */ -"You can also connect by clicking the link. If it opens in the browser, click **Open in mobile app** button." = "リンクをクリックすることでも接続できます。ブラウザで開いた場合は、**モバイルアプリで開く**ボタンをクリックしてください。"; - /* No comment provided by engineer. */ "You can create it later" = "後からでも作成できます"; @@ -3590,9 +3545,6 @@ /* No comment provided by engineer. */ "Your contacts can allow full message deletion." = "連絡先がメッセージの完全削除を許可できます。"; -/* No comment provided by engineer. */ -"Your contacts in SimpleX will see it.\nYou can change it in Settings." = "SimpleX の連絡先に表示されます。\n設定で変更できます。"; - /* No comment provided by engineer. */ "Your contacts will remain connected." = "連絡先は接続されたままになります。"; diff --git a/apps/ios/ja.lproj/SimpleX--iOS--InfoPlist.strings b/apps/ios/ja.lproj/SimpleX--iOS--InfoPlist.strings index 64d806794b..e5eda32632 100644 --- a/apps/ios/ja.lproj/SimpleX--iOS--InfoPlist.strings +++ b/apps/ios/ja.lproj/SimpleX--iOS--InfoPlist.strings @@ -2,14 +2,14 @@ "CFBundleName" = "SimpleX"; /* Privacy - Camera Usage Description */ -"NSCameraUsageDescription" = "SimpleX は、他のユーザーに接続したりビデオ通話を行うために QR コードをスキャンするためにカメラにアクセスする必要があります。"; +"NSCameraUsageDescription" = "SimpleXは他のユーザーに接続したりビデオ通話する際にQRコード読み取りのためにカメラにアクセスする必要があります。"; /* Privacy - Face ID Usage Description */ -"NSFaceIDUsageDescription" = "SimpleX はローカル認証に Face ID を使用します"; +"NSFaceIDUsageDescription" = "SimpleXはローカル認証にFace IDを使用します"; /* Privacy - Microphone Usage Description */ -"NSMicrophoneUsageDescription" = "SimpleX では、音声通話やビデオ通話、および音声メッセージの録音のためにマイクへのアクセスが必要です。"; +"NSMicrophoneUsageDescription" = "SimpleXは音声通話やビデオ通話および音声メッセージの録音のためにマイクにアクセスする必要があります。"; /* Privacy - Photo Library Additions Usage Description */ -"NSPhotoLibraryAddUsageDescription" = "SimpleX は、キャプチャおよび受信したメディアを保存するためにフォト ライブラリにアクセスする必要があります"; +"NSPhotoLibraryAddUsageDescription" = "SimpleXはキャプチャおよび受信したメディアを保存するためにフォトライブラリにアクセスする必要があります"; diff --git a/apps/ios/nl.lproj/Localizable.strings b/apps/ios/nl.lproj/Localizable.strings index 784acf1a9b..91b208ec32 100644 --- a/apps/ios/nl.lproj/Localizable.strings +++ b/apps/ios/nl.lproj/Localizable.strings @@ -64,11 +64,14 @@ /* No comment provided by engineer. */ "[Star on GitHub](https://github.com/simplex-chat/simplex-chat)" = "[Star on GitHub](https://github.com/simplex-chat/simplex-chat)"; +/* No comment provided by engineer. */ +"**Add contact**: to create a new invitation link, or connect via a link you received." = "**Contact toevoegen**: om een nieuwe uitnodigingslink aan te maken, of verbinding te maken via een link die u heeft ontvangen."; + /* No comment provided by engineer. */ "**Add new contact**: to create your one-time QR Code for your contact." = "**Nieuw contact toevoegen**: om uw eenmalige QR-code of link voor uw contact te maken."; /* No comment provided by engineer. */ -"**Create link / QR code** for your contact to use." = "**Maak een link / QR-code aan** die uw contact kan gebruiken."; +"**Create group**: to create a new group." = "**Groep aanmaken**: om een nieuwe groep aan te maken."; /* No comment provided by engineer. */ "**e2e encrypted** audio call" = "**e2e versleuteld** audio gesprek"; @@ -82,18 +85,12 @@ /* No comment provided by engineer. */ "**Most private**: do not use SimpleX Chat notifications server, check messages periodically in the background (depends on how often you use the app)." = "**Meest privé**: gebruik geen SimpleX Chat-notificatie server, controleer berichten regelmatig op de achtergrond (afhankelijk van hoe vaak u de app gebruikt)."; -/* No comment provided by engineer. */ -"**Paste received link** or open it in the browser and tap **Open in mobile app**." = "**Plak de ontvangen link** of open deze in de browser en tik op **Openen in mobiele app**."; - /* No comment provided by engineer. */ "**Please note**: you will NOT be able to recover or change passphrase if you lose it." = "**Let op**: u kunt het wachtwoord NIET herstellen of wijzigen als u het kwijtraakt."; /* No comment provided by engineer. */ "**Recommended**: device token and notifications are sent to SimpleX Chat notification server, but not the message content, size or who it is from." = "**Aanbevolen**: apparaattoken en meldingen worden naar de SimpleX Chat-meldingsserver gestuurd, maar niet de berichtinhoud, -grootte of van wie het afkomstig is."; -/* No comment provided by engineer. */ -"**Scan QR code**: to connect to your contact in person or via video call." = "**Scan QR-code**: om persoonlijk of via een video gesprek verbinding te maken met uw contact."; - /* No comment provided by engineer. */ "**Warning**: Instant push notifications require passphrase saved in Keychain." = "**Waarschuwing**: voor directe push meldingen is een wachtwoord vereist dat is opgeslagen in de Keychain."; @@ -205,6 +202,9 @@ /* No comment provided by engineer. */ "%lld messages blocked" = "%lld berichten geblokkeerd"; +/* No comment provided by engineer. */ +"%lld messages blocked by admin" = "%lld berichten geblokkeerd door beheerder"; + /* No comment provided by engineer. */ "%lld messages marked deleted" = "%lld berichten gemarkeerd als verwijderd"; @@ -280,9 +280,6 @@ /* time interval */ "1 week" = "1 week"; -/* No comment provided by engineer. */ -"1-time link" = "Eenmalige link"; - /* No comment provided by engineer. */ "5 minutes" = "5 minuten"; @@ -350,6 +347,9 @@ /* No comment provided by engineer. */ "Add address to your profile, so that your contacts can share it with other people. Profile update will be sent to your contacts." = "Voeg een adres toe aan uw profiel, zodat uw contacten het met andere mensen kunnen delen. Profiel update wordt naar uw contacten verzonden."; +/* No comment provided by engineer. */ +"Add contact" = "Contact toevoegen"; + /* No comment provided by engineer. */ "Add preset servers" = "Vooraf ingestelde servers toevoegen"; @@ -401,6 +401,9 @@ /* No comment provided by engineer. */ "All group members will remain connected." = "Alle groepsleden blijven verbonden."; +/* No comment provided by engineer. */ +"All messages will be deleted - this cannot be undone!" = "Alle berichten worden verwijderd. Dit kan niet ongedaan worden gemaakt!"; + /* No comment provided by engineer. */ "All messages will be deleted - this cannot be undone! The messages will be deleted ONLY for you." = "Alle berichten worden verwijderd, dit kan niet ongedaan worden gemaakt! De berichten worden ALLEEN voor jou verwijderd."; @@ -423,7 +426,7 @@ "Allow disappearing messages only if your contact allows it to you." = "Sta verdwijnende berichten alleen toe als uw contact dit toestaat."; /* No comment provided by engineer. */ -"Allow irreversible message deletion only if your contact allows it to you." = "Sta het onomkeerbaar verwijderen van berichten alleen toe als uw contact dit toestaat."; +"Allow irreversible message deletion only if your contact allows it to you. (24 hours)" = "Sta het onomkeerbaar verwijderen van berichten alleen toe als uw contact dit toestaat. (24 uur)"; /* No comment provided by engineer. */ "Allow message reactions only if your contact allows them." = "Sta berichtreacties alleen toe als uw contact dit toestaat."; @@ -438,7 +441,7 @@ "Allow sending disappearing messages." = "Toestaan dat verdwijnende berichten worden verzonden."; /* No comment provided by engineer. */ -"Allow to irreversibly delete sent messages." = "Sta toe om verzonden berichten onomkeerbaar te verwijderen."; +"Allow to irreversibly delete sent messages. (24 hours)" = "Sta toe om verzonden berichten onomkeerbaar te verwijderen. (24 uur)"; /* No comment provided by engineer. */ "Allow to send files and media." = "Sta toe om bestanden en media te verzenden."; @@ -459,7 +462,7 @@ "Allow your contacts to call you." = "Sta toe dat uw contacten u bellen."; /* No comment provided by engineer. */ -"Allow your contacts to irreversibly delete sent messages." = "Laat uw contacten verzonden berichten onomkeerbaar verwijderen."; +"Allow your contacts to irreversibly delete sent messages. (24 hours)" = "Laat uw contacten verzonden berichten onomkeerbaar verwijderen. (24 uur)"; /* No comment provided by engineer. */ "Allow your contacts to send disappearing messages." = "Sta toe dat uw contacten verdwijnende berichten verzenden."; @@ -480,7 +483,7 @@ "always" = "altijd"; /* No comment provided by engineer. */ -"Always use relay" = "Verbinden via relais"; +"Always use relay" = "Altijd relay gebruiken"; /* No comment provided by engineer. */ "An empty chat profile with the provided name is created, and the app opens as usual." = "Er wordt een leeg chatprofiel met de opgegeven naam gemaakt en de app wordt zoals gewoonlijk geopend."; @@ -584,18 +587,33 @@ /* No comment provided by engineer. */ "Block" = "Blokkeren"; +/* No comment provided by engineer. */ +"Block for all" = "Blokkeren voor iedereen"; + /* No comment provided by engineer. */ "Block group members" = "Groepsleden blokkeren"; /* No comment provided by engineer. */ "Block member" = "Lid blokkeren"; +/* No comment provided by engineer. */ +"Block member for all?" = "Lid voor iedereen blokkeren?"; + /* No comment provided by engineer. */ "Block member?" = "Lid blokkeren?"; /* No comment provided by engineer. */ "blocked" = "geblokkeerd"; +/* rcv group event chat item */ +"blocked %@" = "geblokkeerd %@"; + +/* blocked chat item */ +"blocked by admin" = "geblokkeerd door beheerder"; + +/* No comment provided by engineer. */ +"Blocked by admin" = "Geblokkeerd door beheerder"; + /* No comment provided by engineer. */ "bold" = "vetgedrukt"; @@ -603,7 +621,7 @@ "Both you and your contact can add message reactions." = "Zowel u als uw contact kunnen berichtreacties toevoegen."; /* No comment provided by engineer. */ -"Both you and your contact can irreversibly delete sent messages." = "Zowel jij als je contact kunnen verzonden berichten onherroepelijk verwijderen."; +"Both you and your contact can irreversibly delete sent messages. (24 hours)" = "Zowel jij als je contact kunnen verzonden berichten onherroepelijk verwijderen. (24 uur)"; /* No comment provided by engineer. */ "Both you and your contact can make calls." = "Zowel u als uw contact kunnen bellen."; @@ -636,7 +654,7 @@ "Calls" = "Oproepen"; /* No comment provided by engineer. */ -"Can't delete user profile!" = "Kan gebruikers profiel niet verwijderen!"; +"Camera not available" = "Camera niet beschikbaar"; /* No comment provided by engineer. */ "Can't invite contact!" = "Kan contact niet uitnodigen!"; @@ -723,6 +741,9 @@ /* No comment provided by engineer. */ "Chat is stopped" = "Chat is gestopt"; +/* No comment provided by engineer. */ +"Chat is stopped. If you already used this database on another device, you should transfer it back before starting chat." = "Chat is gestopt. Als je deze database al op een ander apparaat hebt gebruikt, moet je deze terugzetten voordat je met chatten begint."; + /* No comment provided by engineer. */ "Chat preferences" = "Gesprek voorkeuren"; @@ -750,6 +771,9 @@ /* No comment provided by engineer. */ "Clear conversation?" = "Gesprek wissen?"; +/* No comment provided by engineer. */ +"Clear private notes?" = "Privénotities verwijderen?"; + /* No comment provided by engineer. */ "Clear verification" = "Verwijderd verificatie"; @@ -816,9 +840,6 @@ /* No comment provided by engineer. */ "Connect via link" = "Maak verbinding via link"; -/* No comment provided by engineer. */ -"Connect via link / QR code" = "Maak verbinding via link / QR-code"; - /* No comment provided by engineer. */ "Connect via one-time link" = "Verbinden via een eenmalige link?"; @@ -891,6 +912,9 @@ /* connection information */ "connection:%@" = "verbinding:%@"; +/* profile update event chat item */ +"contact %@ changed to %@" = "contactpersoon %1$@ gewijzigd in %2$@"; + /* No comment provided by engineer. */ "Contact allows" = "Contact maakt het mogelijk"; @@ -960,9 +984,6 @@ /* No comment provided by engineer. */ "Create new profile in [desktop app](https://simplex.chat/downloads/). 💻" = "Maak een nieuw profiel aan in [desktop-app](https://simplex.chat/downloads/). 💻"; -/* No comment provided by engineer. */ -"Create one-time invitation link" = "Maak een eenmalige uitnodiging link"; - /* No comment provided by engineer. */ "Create profile" = "Maak een profiel aan"; @@ -978,9 +999,18 @@ /* No comment provided by engineer. */ "Create your profile" = "Maak je profiel aan"; +/* No comment provided by engineer. */ +"Created at" = "Gemaakt op"; + +/* copied message info */ +"Created at: %@" = "Aangemaakt op: %@"; + /* No comment provided by engineer. */ "Created on %@" = "Gemaakt op %@"; +/* No comment provided by engineer. */ +"Creating link…" = "Link maken…"; + /* No comment provided by engineer. */ "creator" = "creator"; @@ -1096,7 +1126,7 @@ "Delete all files" = "Verwijder alle bestanden"; /* No comment provided by engineer. */ -"Delete and notify contact" = "Contact verwijderen en op de hoogte stellen"; +"Delete and notify contact" = "Verwijderen en contact op de hoogte stellen"; /* No comment provided by engineer. */ "Delete archive" = "Archief verwijderen"; @@ -1299,6 +1329,9 @@ /* No comment provided by engineer. */ "Do it later" = "Doe het later"; +/* No comment provided by engineer. */ +"Do not send history to new members." = "Stuur geen geschiedenis naar nieuwe leden."; + /* No comment provided by engineer. */ "Do NOT use SimpleX for emergency calls." = "Gebruik SimpleX NIET voor noodoproepen."; @@ -1344,6 +1377,9 @@ /* No comment provided by engineer. */ "Enable automatic message deletion?" = "Automatisch verwijderen van berichten aanzetten?"; +/* No comment provided by engineer. */ +"Enable camera access" = "Schakel cameratoegang in"; + /* No comment provided by engineer. */ "Enable for all" = "Inschakelen voor iedereen"; @@ -1398,6 +1434,9 @@ /* notification */ "Encrypted message or another event" = "Versleuteld bericht of een andere gebeurtenis"; +/* notification */ +"Encrypted message: app is stopped" = "Versleuteld bericht: app is gestopt"; + /* notification */ "Encrypted message: database error" = "Versleuteld bericht: database fout"; @@ -1518,6 +1557,9 @@ /* No comment provided by engineer. */ "Error creating member contact" = "Fout bij aanmaken contact"; +/* No comment provided by engineer. */ +"Error creating message" = "Fout bij het maken van een bericht"; + /* No comment provided by engineer. */ "Error creating profile!" = "Fout bij aanmaken van profiel!"; @@ -1569,6 +1611,9 @@ /* No comment provided by engineer. */ "Error loading %@ servers" = "Fout bij het laden van %@ servers"; +/* No comment provided by engineer. */ +"Error opening chat" = "Fout bij het openen van de chat"; + /* No comment provided by engineer. */ "Error receiving file" = "Fout bij ontvangen van bestand"; @@ -1593,6 +1638,9 @@ /* No comment provided by engineer. */ "Error saving user password" = "Fout bij opslaan gebruikers wachtwoord"; +/* No comment provided by engineer. */ +"Error scanning code: %@" = "Fout bij het scannen van code: %@"; + /* No comment provided by engineer. */ "Error sending email" = "Fout bij het verzenden van e-mail"; @@ -1651,7 +1699,7 @@ "Exit without saving" = "Afsluiten zonder opslaan"; /* chat item action */ -"Expand" = "Uitbreiden"; +"Expand" = "Uitklappen"; /* No comment provided by engineer. */ "Export database" = "Database exporteren"; @@ -1798,7 +1846,7 @@ "Group members can add message reactions." = "Groepsleden kunnen berichtreacties toevoegen."; /* No comment provided by engineer. */ -"Group members can irreversibly delete sent messages." = "Groepsleden kunnen verzonden berichten onherroepelijk verwijderen."; +"Group members can irreversibly delete sent messages. (24 hours)" = "Groepsleden kunnen verzonden berichten onherroepelijk verwijderen. (24 uur)"; /* No comment provided by engineer. */ "Group members can send direct messages." = "Groepsleden kunnen directe berichten sturen."; @@ -1866,6 +1914,9 @@ /* No comment provided by engineer. */ "History" = "Geschiedenis"; +/* No comment provided by engineer. */ +"History is not sent to new members." = "Geschiedenis wordt niet naar nieuwe leden gestuurd."; + /* time unit */ "hours" = "uren"; @@ -1890,9 +1941,6 @@ /* No comment provided by engineer. */ "If you can't meet in person, show QR code in a video call, or share the link." = "Als je elkaar niet persoonlijk kunt ontmoeten, laat dan de QR-code zien in een videogesprek of deel de link."; -/* No comment provided by engineer. */ -"If you cannot meet in person, you can **scan QR code in the video call**, or your contact can share an invitation link." = "Als u elkaar niet persoonlijk kunt ontmoeten, kunt u **de QR-code scannen in het video gesprek**, of uw contact kan een uitnodiging link delen."; - /* No comment provided by engineer. */ "If you enter this passcode when opening the app, all app data will be irreversibly removed!" = "Als u deze toegangscode invoert bij het openen van de app, worden alle app-gegevens onomkeerbaar verwijderd!"; @@ -1926,6 +1974,9 @@ /* No comment provided by engineer. */ "Import database" = "Database importeren"; +/* No comment provided by engineer. */ +"Improved message delivery" = "Verbeterde berichtbezorging"; + /* No comment provided by engineer. */ "Improved privacy and security" = "Verbeterde privacy en veiligheid"; @@ -1993,7 +2044,7 @@ "Instant push notifications will be hidden!\n" = "Directe push meldingen worden verborgen!\n"; /* No comment provided by engineer. */ -"Instantly" = "Meteen"; +"Instantly" = "Direct"; /* No comment provided by engineer. */ "Interface" = "Interface"; @@ -2010,9 +2061,21 @@ /* invalid chat item */ "invalid data" = "ongeldige gegevens"; +/* No comment provided by engineer. */ +"Invalid display name!" = "Ongeldige weergavenaam!"; + +/* No comment provided by engineer. */ +"Invalid link" = "Ongeldige link"; + /* No comment provided by engineer. */ "Invalid name!" = "Ongeldige naam!"; +/* No comment provided by engineer. */ +"Invalid QR code" = "Ongeldige QR-code"; + +/* No comment provided by engineer. */ +"Invalid response" = "Ongeldig antwoord"; + /* No comment provided by engineer. */ "Invalid server address!" = "Ongeldig server adres!"; @@ -2091,6 +2154,9 @@ /* No comment provided by engineer. */ "Join group" = "Word lid van groep"; +/* No comment provided by engineer. */ +"Join group conversations" = "Neem deel aan groepsgesprekken"; + /* No comment provided by engineer. */ "Join group?" = "Deelnemen aan groep?"; @@ -2106,9 +2172,15 @@ /* No comment provided by engineer. */ "Joining group" = "Deel nemen aan groep"; +/* No comment provided by engineer. */ +"Keep" = "Bewaar"; + /* No comment provided by engineer. */ "Keep the app open to use it from desktop" = "Houd de app geopend om deze vanaf de desktop te gebruiken"; +/* No comment provided by engineer. */ +"Keep unused invitation?" = "Ongebruikte uitnodiging bewaren?"; + /* No comment provided by engineer. */ "Keep your connections" = "Behoud uw verbindingen"; @@ -2163,6 +2235,9 @@ /* No comment provided by engineer. */ "Live messages" = "Live berichten"; +/* No comment provided by engineer. */ +"Local" = "Lokaal"; + /* No comment provided by engineer. */ "Local name" = "Lokale naam"; @@ -2217,6 +2292,9 @@ /* No comment provided by engineer. */ "Member" = "Lid"; +/* profile update event chat item */ +"member %@ changed to %@" = "lid %1$@ gewijzigd in %2$@"; + /* rcv group event chat item */ "member connected" = "is toegetreden"; @@ -2334,6 +2412,9 @@ /* No comment provided by engineer. */ "never" = "nooit"; +/* No comment provided by engineer. */ +"New chat" = "Nieuw gesprek"; + /* notification */ "New contact request" = "Nieuw contactverzoek"; @@ -2432,9 +2513,6 @@ /* No comment provided by engineer. */ "Off" = "Uit"; -/* No comment provided by engineer. */ -"Off (Local)" = "Uit (lokaal)"; - /* feature offered item */ "offered %@" = "voorgesteld %@"; @@ -2444,6 +2522,9 @@ /* No comment provided by engineer. */ "Ok" = "OK"; +/* No comment provided by engineer. */ +"OK" = "OK"; + /* No comment provided by engineer. */ "Old database" = "Oude database"; @@ -2481,7 +2562,7 @@ "Only you can add message reactions." = "Alleen jij kunt berichtreacties toevoegen."; /* No comment provided by engineer. */ -"Only you can irreversibly delete messages (your contact can mark them for deletion)." = "Alleen jij kunt berichten onomkeerbaar verwijderen (je contact kan ze markeren voor verwijdering)."; +"Only you can irreversibly delete messages (your contact can mark them for deletion). (24 hours)" = "Alleen jij kunt berichten onomkeerbaar verwijderen (je contact kan ze markeren voor verwijdering). (24 uur)"; /* No comment provided by engineer. */ "Only you can make calls." = "Alleen jij kunt bellen."; @@ -2496,7 +2577,7 @@ "Only your contact can add message reactions." = "Alleen uw contact kan berichtreacties toevoegen."; /* No comment provided by engineer. */ -"Only your contact can irreversibly delete messages (you can mark them for deletion)." = "Alleen uw contact kan berichten onherroepelijk verwijderen (u kunt ze markeren voor verwijdering)."; +"Only your contact can irreversibly delete messages (you can mark them for deletion). (24 hours)" = "Alleen uw contact kan berichten onherroepelijk verwijderen (u kunt ze markeren voor verwijdering). (24 uur)"; /* No comment provided by engineer. */ "Only your contact can make calls." = "Alleen je contact kan bellen."; @@ -2529,7 +2610,13 @@ "Open-source protocol and code – anybody can run the servers." = "Open-source protocol en code. Iedereen kan de servers draaien."; /* No comment provided by engineer. */ -"Opening database…" = "Database openen…"; +"Opening app…" = "App openen…"; + +/* No comment provided by engineer. */ +"Or scan QR code" = "Of scan de QR-code"; + +/* No comment provided by engineer. */ +"Or show this code" = "Of laat deze code zien"; /* member role */ "owner" = "Eigenaar"; @@ -2552,8 +2639,8 @@ /* No comment provided by engineer. */ "Password to show" = "Wachtwoord om weer te geven"; -/* No comment provided by engineer. */ -"Paste" = "Plakken"; +/* past/unknown group member */ +"Past member %@" = "Voormalig lid %@"; /* No comment provided by engineer. */ "Paste desktop address" = "Desktopadres plakken"; @@ -2562,10 +2649,10 @@ "Paste image" = "Afbeelding plakken"; /* No comment provided by engineer. */ -"Paste received link" = "Plak de ontvangen link"; +"Paste link to connect!" = "Plak een link om te verbinden!"; -/* placeholder */ -"Paste the link you received to connect with your contact." = "Plak de link die je hebt ontvangen in het vak hieronder om verbinding te maken met je contact."; +/* No comment provided by engineer. */ +"Paste the link you received" = "Plak de link die je hebt ontvangen"; /* No comment provided by engineer. */ "peer-to-peer" = "peer-to-peer"; @@ -2597,6 +2684,9 @@ /* No comment provided by engineer. */ "Please check yours and your contact preferences." = "Controleer de uwe en uw contact voorkeuren."; +/* No comment provided by engineer. */ +"Please contact developers.\nError: %@" = "Neem contact op met ontwikkelaars.\nFout: %@"; + /* No comment provided by engineer. */ "Please contact group admin." = "Neem contact op met de groep beheerder."; @@ -2648,6 +2738,9 @@ /* No comment provided by engineer. */ "Private filenames" = "Privé bestandsnamen"; +/* name of notes to self */ +"Private notes" = "Privé notities"; + /* No comment provided by engineer. */ "Profile and server connections" = "Profiel- en serververbindingen"; @@ -2720,6 +2813,9 @@ /* No comment provided by engineer. */ "Read more in [User Guide](https://simplex.chat/docs/guide/app-settings.html#your-simplex-contact-address)." = "Lees meer in de [Gebruikershandleiding](https://simplex.chat/docs/guide/app-settings.html#uw-simplex-contactadres)."; +/* No comment provided by engineer. */ +"Read more in [User Guide](https://simplex.chat/docs/guide/chat-profiles.html#incognito-mode)." = "Lees meer in de [Gebruikershandleiding](https://simplex.chat/docs/guide/chat-profiles.html#incognito-mode)."; + /* No comment provided by engineer. */ "Read more in [User Guide](https://simplex.chat/docs/guide/readme.html#connect-to-friends)." = "Lees meer in de [Gebruikershandleiding](https://simplex.chat/docs/guide/readme.html#connect-to-friends)."; @@ -2759,6 +2855,9 @@ /* No comment provided by engineer. */ "Receiving via" = "Ontvang via"; +/* No comment provided by engineer. */ +"Recent history and improved [directory bot](simplex:/contact#/?v=1-4&smp=smp%3A%2F%2Fu2dS9sG8nMNURyZwqASV4yROM28Er0luVTx5X1CsMrU%3D%40smp4.simplex.im%2FeXSPwqTkKyDO3px4fLf1wx3MvPdjdLW3%23%2F%3Fv%3D1-2%26dh%3DMCowBQYDK2VuAyEAaiv6MkMH44L2TcYrt_CsX3ZvM11WgbMEUn0hkIKTOho%253D%26srv%3Do5vmywmrnaxalvz6wi3zicyftgio6psuvyniis6gco6bp6ekl4cqj4id.onion)." = "Recente geschiedenis en verbeterde [directory bot](simplex:/contact#/?v=1-4&smp=smp%3A%2F%2Fu2dS9sG8nMNURyZwqASV4yROM28Er0luVTx5X1CsMrU%3D%40smp4.simplex.im%2FeXSPwqTkKyDO3px4fLf1wx3MvPdjdLW3%23%2F%3Fv%3D1-2%26dh%3DMCowBQYDK2VuAyEAaiv6MkMH44L2TcYrt_CsX3ZvM11WgbMEUn0hkIKTOho%253D%26srv%3Do5vmywmrnaxalvz6wi3zicyftgio6psuvyniis6gco6bp6ekl4cqj4id.onion)."; + /* No comment provided by engineer. */ "Recipients see updates as you type them." = "Ontvangers zien updates terwijl u ze typt."; @@ -2813,6 +2912,12 @@ /* rcv group event chat item */ "removed %@" = "verwijderd %@"; +/* profile update event chat item */ +"removed contact address" = "contactadres verwijderd"; + +/* profile update event chat item */ +"removed profile picture" = "profielfoto verwijderd"; + /* rcv group event chat item */ "removed you" = "heeft je verwijderd"; @@ -2864,6 +2969,9 @@ /* No comment provided by engineer. */ "Restore database error" = "Database fout herstellen"; +/* No comment provided by engineer. */ +"Retry" = "Opnieuw proberen"; + /* chat item action */ "Reveal" = "Onthullen"; @@ -2933,6 +3041,9 @@ /* No comment provided by engineer. */ "Save welcome message?" = "Welkomst bericht opslaan?"; +/* message info title */ +"Saved message" = "Opgeslagen bericht"; + /* No comment provided by engineer. */ "Saved WebRTC ICE servers will be removed" = "Opgeslagen WebRTC ICE servers worden verwijderd"; @@ -2954,6 +3065,12 @@ /* No comment provided by engineer. */ "Search" = "Zoeken"; +/* No comment provided by engineer. */ +"Search bar accepts invitation links." = "Zoekbalk accepteert uitnodigingslinks."; + +/* No comment provided by engineer. */ +"Search or paste SimpleX link" = "Zoek of plak een SimpleX link"; + /* network option */ "sec" = "sec"; @@ -3032,6 +3149,9 @@ /* No comment provided by engineer. */ "Send them from gallery or custom keyboards." = "Stuur ze vanuit de galerij of aangepaste toetsenborden."; +/* No comment provided by engineer. */ +"Send up to 100 last messages to new members." = "Stuur tot 100 laatste berichten naar nieuwe leden."; + /* No comment provided by engineer. */ "Sender cancelled file transfer." = "Afzender heeft bestandsoverdracht geannuleerd."; @@ -3104,6 +3224,12 @@ /* No comment provided by engineer. */ "Set it instead of system authentication." = "Stel het in in plaats van systeemverificatie."; +/* profile update event chat item */ +"set new contact address" = "nieuw contactadres instellen"; + +/* profile update event chat item */ +"set new profile picture" = "nieuwe profielfoto instellen"; + /* No comment provided by engineer. */ "Set passcode" = "Toegangscode instellen"; @@ -3135,7 +3261,7 @@ "Share link" = "Deel link"; /* No comment provided by engineer. */ -"Share one-time invitation link" = "Eenmalige uitnodiging link delen"; +"Share this 1-time invite link" = "Deel deze eenmalige uitnodigingslink"; /* No comment provided by engineer. */ "Share with contacts" = "Delen met contacten"; @@ -3213,10 +3339,10 @@ "Somebody" = "Iemand"; /* No comment provided by engineer. */ -"Start a new chat" = "Begin een nieuw gesprek"; +"Start chat" = "Begin gesprek"; /* No comment provided by engineer. */ -"Start chat" = "Begin gesprek"; +"Start chat?" = "Begin chat?"; /* No comment provided by engineer. */ "Start migration" = "Start migratie"; @@ -3287,6 +3413,12 @@ /* No comment provided by engineer. */ "Tap to join incognito" = "Tik om incognito lid te worden"; +/* No comment provided by engineer. */ +"Tap to paste link" = "Tik om de link te plakken"; + +/* No comment provided by engineer. */ +"Tap to scan" = "Tik om te scannen"; + /* No comment provided by engineer. */ "Tap to start a new chat" = "Tik om een nieuw gesprek te starten"; @@ -3332,6 +3464,9 @@ /* No comment provided by engineer. */ "The attempt to change database passphrase was not completed." = "De poging om het wachtwoord van de database te wijzigen is niet voltooid."; +/* No comment provided by engineer. */ +"The code you scanned is not a SimpleX link QR code." = "De code die u heeft gescand is geen SimpleX link QR-code."; + /* No comment provided by engineer. */ "The connection you accepted will be cancelled!" = "De door u geaccepteerde verbinding wordt geannuleerd!"; @@ -3374,15 +3509,12 @@ /* No comment provided by engineer. */ "The servers for new connections of your current chat profile **%@**." = "De servers voor nieuwe verbindingen van uw huidige chat profiel **%@**."; +/* No comment provided by engineer. */ +"The text you pasted is not a SimpleX link." = "De tekst die u hebt geplakt is geen SimpleX link."; + /* No comment provided by engineer. */ "Theme" = "Thema"; -/* No comment provided by engineer. */ -"There should be at least one user profile." = "Er moet ten minste één gebruikers profiel zijn."; - -/* No comment provided by engineer. */ -"There should be at least one visible user profile." = "Er moet ten minste één zichtbaar gebruikers profiel zijn."; - /* No comment provided by engineer. */ "These settings are for your current profile **%@**." = "Deze instellingen zijn voor uw huidige profiel **%@**."; @@ -3404,6 +3536,9 @@ /* No comment provided by engineer. */ "This device name" = "Deze apparaatnaam"; +/* No comment provided by engineer. */ +"This display name is invalid. Please choose another name." = "Deze weergavenaam is ongeldig. Kies een andere naam."; + /* No comment provided by engineer. */ "This group has over %lld members, delivery receipts are not sent." = "Deze groep heeft meer dan %lld -leden, ontvangstbevestigingen worden niet verzonden."; @@ -3465,10 +3600,10 @@ "Trying to connect to the server used to receive messages from this contact." = "Proberen verbinding te maken met de server die wordt gebruikt om berichten van dit contact te ontvangen."; /* No comment provided by engineer. */ -"Turn off" = "Uitschakelen"; +"Turkish interface" = "Turkse interface"; /* No comment provided by engineer. */ -"Turn off notifications?" = "Schakel meldingen uit?"; +"Turn off" = "Uitschakelen"; /* No comment provided by engineer. */ "Turn on" = "Zet aan"; @@ -3479,12 +3614,21 @@ /* No comment provided by engineer. */ "Unblock" = "Deblokkeren"; +/* No comment provided by engineer. */ +"Unblock for all" = "Deblokkeer voor iedereen"; + /* No comment provided by engineer. */ "Unblock member" = "Lid deblokkeren"; +/* No comment provided by engineer. */ +"Unblock member for all?" = "Lid voor iedereen deblokkeren?"; + /* No comment provided by engineer. */ "Unblock member?" = "Lid deblokkeren?"; +/* rcv group event chat item */ +"unblocked %@" = "gedeblokkeerd %@"; + /* item status description */ "Unexpected error: %@" = "Onverwachte fout: %@"; @@ -3518,6 +3662,9 @@ /* No comment provided by engineer. */ "Unknown error" = "Onbekende fout"; +/* No comment provided by engineer. */ +"unknown status" = "onbekende status"; + /* No comment provided by engineer. */ "Unless you use iOS call interface, enable Do Not Disturb mode to avoid interruptions." = "Schakel de modus Niet storen in om onderbrekingen te voorkomen, tenzij u de iOS-oproepinterface gebruikt."; @@ -3542,6 +3689,9 @@ /* No comment provided by engineer. */ "Unread" = "Ongelezen"; +/* No comment provided by engineer. */ +"Up to 100 last messages are sent to new members." = "Er worden maximaal 100 laatste berichten naar nieuwe leden verzonden."; + /* No comment provided by engineer. */ "Update" = "Update"; @@ -3560,6 +3710,9 @@ /* rcv group event chat item */ "updated group profile" = "bijgewerkt groep profiel"; +/* profile update event chat item */ +"updated profile" = "bijgewerkt profiel"; + /* No comment provided by engineer. */ "Updating settings will re-connect the client to all servers." = "Door de instellingen bij te werken, wordt de client opnieuw verbonden met alle servers."; @@ -3593,6 +3746,9 @@ /* No comment provided by engineer. */ "Use new incognito profile" = "Gebruik een nieuw incognitoprofiel"; +/* No comment provided by engineer. */ +"Use only local notifications?" = "Alleen lokale meldingen gebruiken?"; + /* No comment provided by engineer. */ "Use server" = "Gebruik server"; @@ -3642,7 +3798,7 @@ "via one-time link" = "via een eenmalige link"; /* No comment provided by engineer. */ -"via relay" = "via relais"; +"via relay" = "via relay"; /* No comment provided by engineer. */ "Via secure quantum resistant protocol." = "Via een beveiligd kwantumbestendig protocol."; @@ -3665,6 +3821,9 @@ /* No comment provided by engineer. */ "View security code" = "Beveiligingscode bekijken"; +/* chat feature */ +"Visible history" = "Zichtbare geschiedenis"; + /* No comment provided by engineer. */ "Voice message…" = "Spraakbericht…"; @@ -3728,9 +3887,15 @@ /* No comment provided by engineer. */ "When you share an incognito profile with somebody, this profile will be used for the groups they invite you to." = "Wanneer je een incognito profiel met iemand deelt, wordt dit profiel gebruikt voor de groepen waarvoor ze je uitnodigen."; +/* No comment provided by engineer. */ +"With encrypted files and media." = "‐Met versleutelde bestanden en media."; + /* No comment provided by engineer. */ "With optional welcome message." = "Met optioneel welkomst bericht."; +/* No comment provided by engineer. */ +"With reduced battery usage." = "Met verminderd batterijgebruik."; + /* No comment provided by engineer. */ "Wrong database passphrase" = "Verkeerd wachtwoord voor de database"; @@ -3791,11 +3956,11 @@ /* No comment provided by engineer. */ "you are observer" = "jij bent waarnemer"; -/* No comment provided by engineer. */ -"You can accept calls from lock screen, without device and app authentication." = "U kunt oproepen van het vergrendelingsscherm accepteren, zonder apparaat- en app-verificatie."; +/* snd group event chat item */ +"you blocked %@" = "je hebt %@ geblokkeerd"; /* No comment provided by engineer. */ -"You can also connect by clicking the link. If it opens in the browser, click **Open in mobile app** button." = "U kunt ook verbinding maken door op de link te klikken. Als het in de browser wordt geopend, klikt u op de knop **Openen in mobiele app**."; +"You can accept calls from lock screen, without device and app authentication." = "U kunt oproepen van het vergrendelingsscherm accepteren, zonder apparaat- en app-verificatie."; /* No comment provided by engineer. */ "You can create it later" = "U kan het later maken"; @@ -3809,6 +3974,9 @@ /* No comment provided by engineer. */ "You can hide or mute a user profile - swipe it to the right." = "U kunt een gebruikers profiel verbergen of dempen - veeg het naar rechts."; +/* No comment provided by engineer. */ +"You can make it visible to your SimpleX contacts via Settings." = "Je kunt het via Instellingen zichtbaar maken voor je SimpleX contacten."; + /* notification body */ "You can now send messages to %@" = "Je kunt nu berichten sturen naar %@"; @@ -3833,6 +4001,9 @@ /* No comment provided by engineer. */ "You can use markdown to format messages:" = "U kunt markdown gebruiken voor opmaak in berichten:"; +/* No comment provided by engineer. */ +"You can view invitation link again in connection details." = "U kunt de uitnodigingslink opnieuw bekijken in de verbindingsdetails."; + /* No comment provided by engineer. */ "You can't send messages!" = "Je kunt geen berichten versturen!"; @@ -3899,6 +4070,9 @@ /* chat list item description */ "you shared one-time link incognito" = "je hebt een eenmalige link incognito gedeeld"; +/* snd group event chat item */ +"you unblocked %@" = "je hebt %@ gedeblokkeerd"; + /* No comment provided by engineer. */ "You will be connected to group when the group host's device is online, please wait or check later!" = "Je wordt verbonden met de groep wanneer het apparaat van de groep host online is, even geduld a.u.b. of controleer het later!"; @@ -3959,9 +4133,6 @@ /* No comment provided by engineer. */ "Your contacts can allow full message deletion." = "Uw contacten kunnen volledige verwijdering van berichten toestaan."; -/* No comment provided by engineer. */ -"Your contacts in SimpleX will see it.\nYou can change it in Settings." = "Uw contacten in SimpleX kunnen het zien. \nU kunt dit wijzigen in Instellingen."; - /* No comment provided by engineer. */ "Your contacts will remain connected." = "Uw contacten blijven verbonden."; diff --git a/apps/ios/pl.lproj/Localizable.strings b/apps/ios/pl.lproj/Localizable.strings index e0f4c4dee0..bb07d7c01a 100644 --- a/apps/ios/pl.lproj/Localizable.strings +++ b/apps/ios/pl.lproj/Localizable.strings @@ -64,11 +64,14 @@ /* No comment provided by engineer. */ "[Star on GitHub](https://github.com/simplex-chat/simplex-chat)" = "[Daj gwiazdkę na GitHub](https://github.com/simplex-chat/simplex-chat)"; +/* No comment provided by engineer. */ +"**Add contact**: to create a new invitation link, or connect via a link you received." = "**Dodaj kontakt**: aby utworzyć nowy link z zaproszeniem lub połączyć się za pomocą otrzymanego linku."; + /* No comment provided by engineer. */ "**Add new contact**: to create your one-time QR Code for your contact." = "**Dodaj nowy kontakt**: aby stworzyć swój jednorazowy kod QR lub link dla kontaktu."; /* No comment provided by engineer. */ -"**Create link / QR code** for your contact to use." = "**Utwórz link / kod QR**, aby Twój kontakt mógł z niego skorzystać."; +"**Create group**: to create a new group." = "**Utwórz grupę**: aby utworzyć nową grupę."; /* No comment provided by engineer. */ "**e2e encrypted** audio call" = "**szyfrowane e2e** połączenie audio"; @@ -82,18 +85,12 @@ /* No comment provided by engineer. */ "**Most private**: do not use SimpleX Chat notifications server, check messages periodically in the background (depends on how often you use the app)." = "**Najbardziej prywatny**: nie korzystaj z serwera powiadomień SimpleX Chat, sprawdzaj wiadomości okresowo w tle (zależy jak często korzystasz z aplikacji)."; -/* No comment provided by engineer. */ -"**Paste received link** or open it in the browser and tap **Open in mobile app**." = "**Wklej otrzymany link** lub otwórz go w przeglądarce i dotknij **Otwórz w aplikacji mobilnej**."; - /* No comment provided by engineer. */ "**Please note**: you will NOT be able to recover or change passphrase if you lose it." = "**Uwaga**: NIE będziesz w stanie odzyskać lub zmienić hasła, jeśli je stracisz."; /* No comment provided by engineer. */ "**Recommended**: device token and notifications are sent to SimpleX Chat notification server, but not the message content, size or who it is from." = "**Zalecane**: token urządzenia i powiadomienia są wysyłane do serwera powiadomień SimpleX Chat, ale nie treść wiadomości, rozmiar lub od kogo jest."; -/* No comment provided by engineer. */ -"**Scan QR code**: to connect to your contact in person or via video call." = "**Skanuj kod QR**: aby połączyć się z kontaktem osobiście lub za pomocą połączenia wideo."; - /* No comment provided by engineer. */ "**Warning**: Instant push notifications require passphrase saved in Keychain." = "**Uwaga**: Natychmiastowe powiadomienia push wymagają hasła zapisanego w Keychain."; @@ -205,6 +202,9 @@ /* No comment provided by engineer. */ "%lld messages blocked" = "%lld wiadomości zablokowanych"; +/* No comment provided by engineer. */ +"%lld messages blocked by admin" = "%lld wiadomości zablokowanych przez admina"; + /* No comment provided by engineer. */ "%lld messages marked deleted" = "%lld wiadomości oznaczonych do usunięcia"; @@ -280,9 +280,6 @@ /* time interval */ "1 week" = "1 tydzień"; -/* No comment provided by engineer. */ -"1-time link" = "1-razowy link"; - /* No comment provided by engineer. */ "5 minutes" = "5 minut"; @@ -350,6 +347,9 @@ /* No comment provided by engineer. */ "Add address to your profile, so that your contacts can share it with other people. Profile update will be sent to your contacts." = "Dodaj adres do swojego profilu, aby Twoje kontakty mogły go udostępnić innym osobom. Aktualizacja profilu zostanie wysłana do Twoich kontaktów."; +/* No comment provided by engineer. */ +"Add contact" = "Dodaj kontakt"; + /* No comment provided by engineer. */ "Add preset servers" = "Dodaj gotowe serwery"; @@ -401,6 +401,9 @@ /* No comment provided by engineer. */ "All group members will remain connected." = "Wszyscy członkowie grupy pozostaną połączeni."; +/* No comment provided by engineer. */ +"All messages will be deleted - this cannot be undone!" = "Wszystkie wiadomości zostaną usunięte – nie można tego cofnąć!"; + /* No comment provided by engineer. */ "All messages will be deleted - this cannot be undone! The messages will be deleted ONLY for you." = "Wszystkie wiadomości zostaną usunięte - nie można tego cofnąć! Wiadomości zostaną usunięte TYLKO dla Ciebie."; @@ -423,7 +426,7 @@ "Allow disappearing messages only if your contact allows it to you." = "Zezwól na znikające wiadomości tylko wtedy, gdy Twój kontakt Ci na to pozwoli."; /* No comment provided by engineer. */ -"Allow irreversible message deletion only if your contact allows it to you." = "Zezwalaj na nieodwracalne usuwanie wiadomości tylko wtedy, gdy Twój kontakt Ci na to pozwoli."; +"Allow irreversible message deletion only if your contact allows it to you. (24 hours)" = "Zezwalaj na nieodwracalne usuwanie wiadomości tylko wtedy, gdy Twój kontakt Ci na to pozwoli. (24 godziny)"; /* No comment provided by engineer. */ "Allow message reactions only if your contact allows them." = "Zezwalaj na reakcje wiadomości tylko wtedy, gdy zezwala na to Twój kontakt."; @@ -438,7 +441,7 @@ "Allow sending disappearing messages." = "Zezwól na wysyłanie znikających wiadomości."; /* No comment provided by engineer. */ -"Allow to irreversibly delete sent messages." = "Zezwól na nieodwracalne usunięcie wysłanych wiadomości."; +"Allow to irreversibly delete sent messages. (24 hours)" = "Zezwól na nieodwracalne usunięcie wysłanych wiadomości. (24 godziny)"; /* No comment provided by engineer. */ "Allow to send files and media." = "Pozwól na wysyłanie plików i mediów."; @@ -459,7 +462,7 @@ "Allow your contacts to call you." = "Zezwól swoim kontaktom na połączenia do Ciebie."; /* No comment provided by engineer. */ -"Allow your contacts to irreversibly delete sent messages." = "Zezwól swoim kontaktom na nieodwracalne usuwanie wysłanych wiadomości."; +"Allow your contacts to irreversibly delete sent messages. (24 hours)" = "Zezwól swoim kontaktom na nieodwracalne usuwanie wysłanych wiadomości. (24 godziny)"; /* No comment provided by engineer. */ "Allow your contacts to send disappearing messages." = "Zezwól swoim kontaktom na wysyłanie znikających wiadomości."; @@ -584,18 +587,33 @@ /* No comment provided by engineer. */ "Block" = "Zablokuj"; +/* No comment provided by engineer. */ +"Block for all" = "Zablokuj dla wszystkich"; + /* No comment provided by engineer. */ "Block group members" = "Blokuj członków grupy"; /* No comment provided by engineer. */ "Block member" = "Zablokuj członka"; +/* No comment provided by engineer. */ +"Block member for all?" = "Zablokować członka dla wszystkich?"; + /* No comment provided by engineer. */ "Block member?" = "Zablokować członka?"; /* No comment provided by engineer. */ "blocked" = "zablokowany"; +/* rcv group event chat item */ +"blocked %@" = "zablokowany %@"; + +/* blocked chat item */ +"blocked by admin" = "zablokowany przez admina"; + +/* No comment provided by engineer. */ +"Blocked by admin" = "Zablokowany przez admina"; + /* No comment provided by engineer. */ "bold" = "pogrubiona"; @@ -603,7 +621,7 @@ "Both you and your contact can add message reactions." = "Zarówno Ty, jak i Twój kontakt możecie dodawać reakcje wiadomości."; /* No comment provided by engineer. */ -"Both you and your contact can irreversibly delete sent messages." = "Zarówno Ty, jak i Twój kontakt możecie nieodwracalnie usunąć wysłane wiadomości."; +"Both you and your contact can irreversibly delete sent messages. (24 hours)" = "Zarówno Ty, jak i Twój kontakt możecie nieodwracalnie usunąć wysłane wiadomości. (24 godziny)"; /* No comment provided by engineer. */ "Both you and your contact can make calls." = "Zarówno Ty, jak i Twój kontakt możecie nawiązywać połączenia."; @@ -636,7 +654,7 @@ "Calls" = "Połączenia"; /* No comment provided by engineer. */ -"Can't delete user profile!" = "Nie można usunąć profilu użytkownika!"; +"Camera not available" = "Kamera nie dostępna"; /* No comment provided by engineer. */ "Can't invite contact!" = "Nie można zaprosić kontaktu!"; @@ -723,6 +741,9 @@ /* No comment provided by engineer. */ "Chat is stopped" = "Czat jest zatrzymany"; +/* No comment provided by engineer. */ +"Chat is stopped. If you already used this database on another device, you should transfer it back before starting chat." = "Czat został zatrzymany. Jeśli korzystałeś już z tej bazy danych na innym urządzeniu, powinieneś przenieść ją z powrotem przed rozpoczęciem czatu."; + /* No comment provided by engineer. */ "Chat preferences" = "Preferencje czatu"; @@ -750,6 +771,9 @@ /* No comment provided by engineer. */ "Clear conversation?" = "Wyczyścić rozmowę?"; +/* No comment provided by engineer. */ +"Clear private notes?" = "Wyczyścić prywatne notatki?"; + /* No comment provided by engineer. */ "Clear verification" = "Wyczyść weryfikację"; @@ -816,9 +840,6 @@ /* No comment provided by engineer. */ "Connect via link" = "Połącz się przez link"; -/* No comment provided by engineer. */ -"Connect via link / QR code" = "Połącz się przez link / kod QR"; - /* No comment provided by engineer. */ "Connect via one-time link" = "Połącz przez jednorazowy link"; @@ -891,6 +912,9 @@ /* connection information */ "connection:%@" = "połączenie: %@"; +/* profile update event chat item */ +"contact %@ changed to %@" = "kontakt %1$@ zmieniony na %2$@"; + /* No comment provided by engineer. */ "Contact allows" = "Kontakt pozwala"; @@ -960,9 +984,6 @@ /* No comment provided by engineer. */ "Create new profile in [desktop app](https://simplex.chat/downloads/). 💻" = "Utwórz nowy profil w [aplikacji desktopowej](https://simplex.chat/downloads/). 💻"; -/* No comment provided by engineer. */ -"Create one-time invitation link" = "Utwórz jednorazowy link do zaproszenia"; - /* No comment provided by engineer. */ "Create profile" = "Utwórz profil"; @@ -978,9 +999,18 @@ /* No comment provided by engineer. */ "Create your profile" = "Utwórz swój profil"; +/* No comment provided by engineer. */ +"Created at" = "Utworzony o"; + +/* copied message info */ +"Created at: %@" = "Utworzony o: %@"; + /* No comment provided by engineer. */ "Created on %@" = "Utworzony w dniu %@"; +/* No comment provided by engineer. */ +"Creating link…" = "Tworzenie linku…"; + /* No comment provided by engineer. */ "creator" = "twórca"; @@ -1299,6 +1329,9 @@ /* No comment provided by engineer. */ "Do it later" = "Zrób to później"; +/* No comment provided by engineer. */ +"Do not send history to new members." = "Nie wysyłaj historii do nowych członków."; + /* No comment provided by engineer. */ "Do NOT use SimpleX for emergency calls." = "NIE używaj SimpleX do połączeń alarmowych."; @@ -1344,6 +1377,9 @@ /* No comment provided by engineer. */ "Enable automatic message deletion?" = "Czy włączyć automatyczne usuwanie wiadomości?"; +/* No comment provided by engineer. */ +"Enable camera access" = "Włącz dostęp do kamery"; + /* No comment provided by engineer. */ "Enable for all" = "Włącz dla wszystkich"; @@ -1398,6 +1434,9 @@ /* notification */ "Encrypted message or another event" = "Zaszyfrowana wiadomość lub inne zdarzenie"; +/* notification */ +"Encrypted message: app is stopped" = "Zaszyfrowana wiadomość: aplikacja jest zatrzymana"; + /* notification */ "Encrypted message: database error" = "Zaszyfrowana wiadomość: błąd bazy danych"; @@ -1518,6 +1557,9 @@ /* No comment provided by engineer. */ "Error creating member contact" = "Błąd tworzenia kontaktu członka"; +/* No comment provided by engineer. */ +"Error creating message" = "Błąd tworzenia wiadomości"; + /* No comment provided by engineer. */ "Error creating profile!" = "Błąd tworzenia profilu!"; @@ -1569,6 +1611,9 @@ /* No comment provided by engineer. */ "Error loading %@ servers" = "Błąd ładowania %@ serwerów"; +/* No comment provided by engineer. */ +"Error opening chat" = "Błąd otwierania czatu"; + /* No comment provided by engineer. */ "Error receiving file" = "Błąd odbioru pliku"; @@ -1593,6 +1638,9 @@ /* No comment provided by engineer. */ "Error saving user password" = "Błąd zapisu hasła użytkownika"; +/* No comment provided by engineer. */ +"Error scanning code: %@" = "Błąd skanowanie kodu: %@"; + /* No comment provided by engineer. */ "Error sending email" = "Błąd wysyłania e-mail"; @@ -1798,7 +1846,7 @@ "Group members can add message reactions." = "Członkowie grupy mogą dodawać reakcje wiadomości."; /* No comment provided by engineer. */ -"Group members can irreversibly delete sent messages." = "Członkowie grupy mogą nieodwracalnie usuwać wysłane wiadomości."; +"Group members can irreversibly delete sent messages. (24 hours)" = "Członkowie grupy mogą nieodwracalnie usuwać wysłane wiadomości. (24 godziny)"; /* No comment provided by engineer. */ "Group members can send direct messages." = "Członkowie grupy mogą wysyłać bezpośrednie wiadomości."; @@ -1866,6 +1914,9 @@ /* No comment provided by engineer. */ "History" = "Historia"; +/* No comment provided by engineer. */ +"History is not sent to new members." = "Historia nie jest wysyłana do nowych członków."; + /* time unit */ "hours" = "godziny"; @@ -1890,9 +1941,6 @@ /* No comment provided by engineer. */ "If you can't meet in person, show QR code in a video call, or share the link." = "Jeśli nie możesz spotkać się osobiście, pokaż kod QR w rozmowie wideo lub udostępnij link."; -/* No comment provided by engineer. */ -"If you cannot meet in person, you can **scan QR code in the video call**, or your contact can share an invitation link." = "Jeśli nie możesz spotkać się osobiście, możesz **zeskanować kod QR w rozmowie wideo** lub Twój kontakt może udostępnić link z zaproszeniem."; - /* No comment provided by engineer. */ "If you enter this passcode when opening the app, all app data will be irreversibly removed!" = "Jeśli wprowadzisz ten pin podczas otwierania aplikacji, wszystkie dane aplikacji zostaną nieodwracalnie usunięte!"; @@ -1926,6 +1974,9 @@ /* No comment provided by engineer. */ "Import database" = "Importuj bazę danych"; +/* No comment provided by engineer. */ +"Improved message delivery" = "Ulepszona dostawa wiadomości"; + /* No comment provided by engineer. */ "Improved privacy and security" = "Zwiększona prywatność i bezpieczeństwo"; @@ -2010,9 +2061,21 @@ /* invalid chat item */ "invalid data" = "nieprawidłowe dane"; +/* No comment provided by engineer. */ +"Invalid display name!" = "Nieprawidłowa nazwa wyświetlana!"; + +/* No comment provided by engineer. */ +"Invalid link" = "Nieprawidłowy link"; + /* No comment provided by engineer. */ "Invalid name!" = "Nieprawidłowa nazwa!"; +/* No comment provided by engineer. */ +"Invalid QR code" = "Nieprawidłowy kod QR"; + +/* No comment provided by engineer. */ +"Invalid response" = "Nieprawidłowa odpowiedź"; + /* No comment provided by engineer. */ "Invalid server address!" = "Nieprawidłowy adres serwera!"; @@ -2091,6 +2154,9 @@ /* No comment provided by engineer. */ "Join group" = "Dołącz do grupy"; +/* No comment provided by engineer. */ +"Join group conversations" = "Dołącz do grupowej rozmowy"; + /* No comment provided by engineer. */ "Join group?" = "Dołączyć do grupy?"; @@ -2106,9 +2172,15 @@ /* No comment provided by engineer. */ "Joining group" = "Dołączanie do grupy"; +/* No comment provided by engineer. */ +"Keep" = "Zachowaj"; + /* No comment provided by engineer. */ "Keep the app open to use it from desktop" = "Zostaw aplikację otwartą i używaj ją z komputera"; +/* No comment provided by engineer. */ +"Keep unused invitation?" = "Zachować nieużyte zaproszenie?"; + /* No comment provided by engineer. */ "Keep your connections" = "Zachowaj swoje połączenia"; @@ -2163,6 +2235,9 @@ /* No comment provided by engineer. */ "Live messages" = "Wiadomości na żywo"; +/* No comment provided by engineer. */ +"Local" = "Lokalnie"; + /* No comment provided by engineer. */ "Local name" = "Nazwa lokalna"; @@ -2217,6 +2292,9 @@ /* No comment provided by engineer. */ "Member" = "Członek"; +/* profile update event chat item */ +"member %@ changed to %@" = "członek %1$@ zmieniony na %2$@"; + /* rcv group event chat item */ "member connected" = "połączony"; @@ -2334,6 +2412,9 @@ /* No comment provided by engineer. */ "never" = "nigdy"; +/* No comment provided by engineer. */ +"New chat" = "Nowy czat"; + /* notification */ "New contact request" = "Nowa prośba o kontakt"; @@ -2432,9 +2513,6 @@ /* No comment provided by engineer. */ "Off" = "Wyłączony"; -/* No comment provided by engineer. */ -"Off (Local)" = "Wyłączony (Lokalnie)"; - /* feature offered item */ "offered %@" = "zaoferował %@"; @@ -2444,6 +2522,9 @@ /* No comment provided by engineer. */ "Ok" = "Ok"; +/* No comment provided by engineer. */ +"OK" = "OK"; + /* No comment provided by engineer. */ "Old database" = "Stara baza danych"; @@ -2481,7 +2562,7 @@ "Only you can add message reactions." = "Tylko Ty możesz dodawać reakcje wiadomości."; /* No comment provided by engineer. */ -"Only you can irreversibly delete messages (your contact can mark them for deletion)." = "Tylko Ty możesz nieodwracalnie usunąć wiadomości (Twój kontakt może oznaczyć je do usunięcia)."; +"Only you can irreversibly delete messages (your contact can mark them for deletion). (24 hours)" = "Tylko Ty możesz nieodwracalnie usunąć wiadomości (Twój kontakt może oznaczyć je do usunięcia). (24 godziny)"; /* No comment provided by engineer. */ "Only you can make calls." = "Tylko Ty możesz wykonywać połączenia."; @@ -2496,7 +2577,7 @@ "Only your contact can add message reactions." = "Tylko Twój kontakt może dodawać reakcje wiadomości."; /* No comment provided by engineer. */ -"Only your contact can irreversibly delete messages (you can mark them for deletion)." = "Tylko Twój kontakt może nieodwracalnie usunąć wiadomości (możesz oznaczyć je do usunięcia)."; +"Only your contact can irreversibly delete messages (you can mark them for deletion). (24 hours)" = "Tylko Twój kontakt może nieodwracalnie usunąć wiadomości (możesz oznaczyć je do usunięcia). (24 godziny)"; /* No comment provided by engineer. */ "Only your contact can make calls." = "Tylko Twój kontakt może wykonywać połączenia."; @@ -2529,7 +2610,13 @@ "Open-source protocol and code – anybody can run the servers." = "Otwarto źródłowy protokół i kod - każdy może uruchomić serwery."; /* No comment provided by engineer. */ -"Opening database…" = "Otwieranie bazy danych…"; +"Opening app…" = "Otwieranie aplikacji…"; + +/* No comment provided by engineer. */ +"Or scan QR code" = "Lub zeskanuj kod QR"; + +/* No comment provided by engineer. */ +"Or show this code" = "Lub pokaż ten kod"; /* member role */ "owner" = "właściciel"; @@ -2552,8 +2639,8 @@ /* No comment provided by engineer. */ "Password to show" = "Hasło do wyświetlenia"; -/* No comment provided by engineer. */ -"Paste" = "Wklej"; +/* past/unknown group member */ +"Past member %@" = "Były członek %@"; /* No comment provided by engineer. */ "Paste desktop address" = "Wklej adres komputera"; @@ -2562,10 +2649,10 @@ "Paste image" = "Wklej obraz"; /* No comment provided by engineer. */ -"Paste received link" = "Wklej otrzymany link"; +"Paste link to connect!" = "Wklej link, aby połączyć!"; -/* placeholder */ -"Paste the link you received to connect with your contact." = "Wklej otrzymany link w pole poniżej, aby połączyć się z kontaktem."; +/* No comment provided by engineer. */ +"Paste the link you received" = "Wklej link, który otrzymałeś"; /* No comment provided by engineer. */ "peer-to-peer" = "peer-to-peer"; @@ -2597,6 +2684,9 @@ /* No comment provided by engineer. */ "Please check yours and your contact preferences." = "Proszę sprawdzić preferencje Twoje i Twojego kontaktu."; +/* No comment provided by engineer. */ +"Please contact developers.\nError: %@" = "Proszę skontaktować się z deweloperami.\nBłąd: %@"; + /* No comment provided by engineer. */ "Please contact group admin." = "Skontaktuj się z administratorem grupy."; @@ -2648,6 +2738,9 @@ /* No comment provided by engineer. */ "Private filenames" = "Prywatne nazwy plików"; +/* name of notes to self */ +"Private notes" = "Prywatne notatki"; + /* No comment provided by engineer. */ "Profile and server connections" = "Profil i połączenia z serwerem"; @@ -2720,6 +2813,9 @@ /* No comment provided by engineer. */ "Read more in [User Guide](https://simplex.chat/docs/guide/app-settings.html#your-simplex-contact-address)." = "Przeczytaj więcej w [Podręczniku Użytkownika](https://simplex.chat/docs/guide/app-settings.html#your-simplex-contact-address)."; +/* No comment provided by engineer. */ +"Read more in [User Guide](https://simplex.chat/docs/guide/chat-profiles.html#incognito-mode)." = "Przeczytaj więcej w [Poradniku Użytkownika](https://simplex.chat/docs/guide/chat-profiles.html#incognito-mode)."; + /* No comment provided by engineer. */ "Read more in [User Guide](https://simplex.chat/docs/guide/readme.html#connect-to-friends)." = "Przeczytaj więcej w [Podręczniku Użytkownika](https://simplex.chat/docs/guide/readme.html#connect-to-friends)."; @@ -2759,6 +2855,9 @@ /* No comment provided by engineer. */ "Receiving via" = "Odbieranie przez"; +/* No comment provided by engineer. */ +"Recent history and improved [directory bot](simplex:/contact#/?v=1-4&smp=smp%3A%2F%2Fu2dS9sG8nMNURyZwqASV4yROM28Er0luVTx5X1CsMrU%3D%40smp4.simplex.im%2FeXSPwqTkKyDO3px4fLf1wx3MvPdjdLW3%23%2F%3Fv%3D1-2%26dh%3DMCowBQYDK2VuAyEAaiv6MkMH44L2TcYrt_CsX3ZvM11WgbMEUn0hkIKTOho%253D%26srv%3Do5vmywmrnaxalvz6wi3zicyftgio6psuvyniis6gco6bp6ekl4cqj4id.onion)." = "Ostania historia i ulepszony [bot adresowy](simplex:/contact#/?v=1-4&smp=smp%3A%2F%2Fu2dS9sG8nMNURyZwqASV4yROM28Er0luVTx5X1CsMrU%3D%40smp4.simplex.im%2FeXSPwqTkKyDO3px4fLf1wx3MvPdjdLW3%23%2F%3Fv%3D1-2%26dh%3DMCowBQYDK2VuAyEAaiv6MkMH44L2TcYrt_CsX3ZvM11WgbMEUn0hkIKTOho%253D%26srv%3Do5vmywmrnaxalvz6wi3zicyftgio6psuvyniis6gco6bp6ekl4cqj4id.onion)."; + /* No comment provided by engineer. */ "Recipients see updates as you type them." = "Odbiorcy widzą aktualizacje podczas ich wpisywania."; @@ -2813,6 +2912,12 @@ /* rcv group event chat item */ "removed %@" = "usunięto %@"; +/* profile update event chat item */ +"removed contact address" = "usunięto adres kontaktu"; + +/* profile update event chat item */ +"removed profile picture" = "usunięto zdjęcie profilu"; + /* rcv group event chat item */ "removed you" = "usunął cię"; @@ -2864,6 +2969,9 @@ /* No comment provided by engineer. */ "Restore database error" = "Błąd przywracania bazy danych"; +/* No comment provided by engineer. */ +"Retry" = "Ponów"; + /* chat item action */ "Reveal" = "Ujawnij"; @@ -2933,6 +3041,9 @@ /* No comment provided by engineer. */ "Save welcome message?" = "Zapisać wiadomość powitalną?"; +/* message info title */ +"Saved message" = "Zachowano wiadomość"; + /* No comment provided by engineer. */ "Saved WebRTC ICE servers will be removed" = "Zapisane serwery WebRTC ICE zostaną usunięte"; @@ -2954,6 +3065,12 @@ /* No comment provided by engineer. */ "Search" = "Szukaj"; +/* No comment provided by engineer. */ +"Search bar accepts invitation links." = "Pasek wyszukiwania akceptuje linki zaproszenia."; + +/* No comment provided by engineer. */ +"Search or paste SimpleX link" = "Wyszukaj lub wklej link SimpleX"; + /* network option */ "sec" = "sek"; @@ -3032,6 +3149,9 @@ /* No comment provided by engineer. */ "Send them from gallery or custom keyboards." = "Wyślij je z galerii lub niestandardowych klawiatur."; +/* No comment provided by engineer. */ +"Send up to 100 last messages to new members." = "Wysyłaj do 100 ostatnich wiadomości do nowych członków."; + /* No comment provided by engineer. */ "Sender cancelled file transfer." = "Nadawca anulował transfer pliku."; @@ -3104,6 +3224,12 @@ /* No comment provided by engineer. */ "Set it instead of system authentication." = "Ustaw go zamiast uwierzytelniania systemowego."; +/* profile update event chat item */ +"set new contact address" = "ustaw nowy adres kontaktu"; + +/* profile update event chat item */ +"set new profile picture" = "ustaw nowe zdjęcie profilu"; + /* No comment provided by engineer. */ "Set passcode" = "Ustaw pin"; @@ -3135,7 +3261,7 @@ "Share link" = "Udostępnij link"; /* No comment provided by engineer. */ -"Share one-time invitation link" = "Jednorazowy link zaproszenia"; +"Share this 1-time invite link" = "Udostępnij ten jednorazowy link"; /* No comment provided by engineer. */ "Share with contacts" = "Udostępnij kontaktom"; @@ -3213,10 +3339,10 @@ "Somebody" = "Ktoś"; /* No comment provided by engineer. */ -"Start a new chat" = "Rozpocznij nowy czat"; +"Start chat" = "Rozpocznij czat"; /* No comment provided by engineer. */ -"Start chat" = "Rozpocznij czat"; +"Start chat?" = "Rozpocząć czat?"; /* No comment provided by engineer. */ "Start migration" = "Rozpocznij migrację"; @@ -3287,6 +3413,12 @@ /* No comment provided by engineer. */ "Tap to join incognito" = "Dotnij, aby dołączyć w trybie incognito"; +/* No comment provided by engineer. */ +"Tap to paste link" = "Dotknij, aby wkleić link"; + +/* No comment provided by engineer. */ +"Tap to scan" = "Dotknij, aby zeskanować"; + /* No comment provided by engineer. */ "Tap to start a new chat" = "Dotknij, aby rozpocząć nowy czat"; @@ -3332,6 +3464,9 @@ /* No comment provided by engineer. */ "The attempt to change database passphrase was not completed." = "Próba zmiany hasła bazy danych nie została zakończona."; +/* No comment provided by engineer. */ +"The code you scanned is not a SimpleX link QR code." = "Kod, który zeskanowałeś nie jest kodem QR linku SimpleX."; + /* No comment provided by engineer. */ "The connection you accepted will be cancelled!" = "Zaakceptowane przez Ciebie połączenie zostanie anulowane!"; @@ -3374,15 +3509,12 @@ /* No comment provided by engineer. */ "The servers for new connections of your current chat profile **%@**." = "Serwery dla nowych połączeń bieżącego profilu czatu **%@**."; +/* No comment provided by engineer. */ +"The text you pasted is not a SimpleX link." = "Tekst, który wkleiłeś nie jest linkiem SimpleX."; + /* No comment provided by engineer. */ "Theme" = "Motyw"; -/* No comment provided by engineer. */ -"There should be at least one user profile." = "Powinien istnieć co najmniej jeden profil użytkownika."; - -/* No comment provided by engineer. */ -"There should be at least one visible user profile." = "Powinien istnieć co najmniej jeden widoczny profil użytkownika."; - /* No comment provided by engineer. */ "These settings are for your current profile **%@**." = "Te ustawienia dotyczą Twojego bieżącego profilu **%@**."; @@ -3404,6 +3536,9 @@ /* No comment provided by engineer. */ "This device name" = "Nazwa tego urządzenia"; +/* No comment provided by engineer. */ +"This display name is invalid. Please choose another name." = "Nazwa wyświetlana jest nieprawidłowa. Proszę wybrać inną nazwę."; + /* No comment provided by engineer. */ "This group has over %lld members, delivery receipts are not sent." = "Ta grupa ma ponad %lld członków, potwierdzenia dostawy nie są wysyłane."; @@ -3465,10 +3600,10 @@ "Trying to connect to the server used to receive messages from this contact." = "Próbowanie połączenia z serwerem używanym do odbierania wiadomości od tego kontaktu."; /* No comment provided by engineer. */ -"Turn off" = "Wyłącz"; +"Turkish interface" = "Turecki interfejs"; /* No comment provided by engineer. */ -"Turn off notifications?" = "Wyłączyć powiadomienia?"; +"Turn off" = "Wyłącz"; /* No comment provided by engineer. */ "Turn on" = "Włącz"; @@ -3479,12 +3614,21 @@ /* No comment provided by engineer. */ "Unblock" = "Odblokuj"; +/* No comment provided by engineer. */ +"Unblock for all" = "Odblokuj dla wszystkich"; + /* No comment provided by engineer. */ "Unblock member" = "Odblokuj członka"; +/* No comment provided by engineer. */ +"Unblock member for all?" = "Odblokować członka dla wszystkich?"; + /* No comment provided by engineer. */ "Unblock member?" = "Odblokować członka?"; +/* rcv group event chat item */ +"unblocked %@" = "odblokowano %@"; + /* item status description */ "Unexpected error: %@" = "Nieoczekiwany błąd: %@"; @@ -3518,6 +3662,9 @@ /* No comment provided by engineer. */ "Unknown error" = "Nieznany błąd"; +/* No comment provided by engineer. */ +"unknown status" = "nieznany status"; + /* No comment provided by engineer. */ "Unless you use iOS call interface, enable Do Not Disturb mode to avoid interruptions." = "O ile nie korzystasz z interfejsu połączeń systemu iOS, włącz tryb Nie przeszkadzać, aby uniknąć przerywania."; @@ -3542,6 +3689,9 @@ /* No comment provided by engineer. */ "Unread" = "Nieprzeczytane"; +/* No comment provided by engineer. */ +"Up to 100 last messages are sent to new members." = "Do nowych członków wysyłanych jest do 100 ostatnich wiadomości."; + /* No comment provided by engineer. */ "Update" = "Aktualizuj"; @@ -3560,6 +3710,9 @@ /* rcv group event chat item */ "updated group profile" = "zaktualizowano profil grupy"; +/* profile update event chat item */ +"updated profile" = "zaktualizowano profil"; + /* No comment provided by engineer. */ "Updating settings will re-connect the client to all servers." = "Aktualizacja ustawień spowoduje ponowne połączenie klienta ze wszystkimi serwerami."; @@ -3593,6 +3746,9 @@ /* No comment provided by engineer. */ "Use new incognito profile" = "Użyj nowego profilu incognito"; +/* No comment provided by engineer. */ +"Use only local notifications?" = "Używać tylko lokalnych powiadomień?"; + /* No comment provided by engineer. */ "Use server" = "Użyj serwera"; @@ -3665,6 +3821,9 @@ /* No comment provided by engineer. */ "View security code" = "Pokaż kod bezpieczeństwa"; +/* chat feature */ +"Visible history" = "Widoczna historia"; + /* No comment provided by engineer. */ "Voice message…" = "Wiadomość głosowa…"; @@ -3728,9 +3887,15 @@ /* No comment provided by engineer. */ "When you share an incognito profile with somebody, this profile will be used for the groups they invite you to." = "Gdy udostępnisz komuś profil incognito, będzie on używany w grupach, do których Cię zaprosi."; +/* No comment provided by engineer. */ +"With encrypted files and media." = "Z zaszyfrowanymi plikami i multimediami."; + /* No comment provided by engineer. */ "With optional welcome message." = "Z opcjonalną wiadomością powitalną."; +/* No comment provided by engineer. */ +"With reduced battery usage." = "Ze zmniejszonym zużyciem baterii."; + /* No comment provided by engineer. */ "Wrong database passphrase" = "Nieprawidłowe hasło bazy danych"; @@ -3791,11 +3956,11 @@ /* No comment provided by engineer. */ "you are observer" = "jesteś obserwatorem"; -/* No comment provided by engineer. */ -"You can accept calls from lock screen, without device and app authentication." = "Możesz przyjmować połączenia z ekranu blokady, bez uwierzytelniania urządzenia i aplikacji."; +/* snd group event chat item */ +"you blocked %@" = "zablokowałeś %@"; /* No comment provided by engineer. */ -"You can also connect by clicking the link. If it opens in the browser, click **Open in mobile app** button." = "Możesz też połączyć się klikając w link. Jeśli otworzy się on w przeglądarce, kliknij przycisk **Otwórz w aplikacji mobilnej**."; +"You can accept calls from lock screen, without device and app authentication." = "Możesz przyjmować połączenia z ekranu blokady, bez uwierzytelniania urządzenia i aplikacji."; /* No comment provided by engineer. */ "You can create it later" = "Możesz go utworzyć później"; @@ -3809,6 +3974,9 @@ /* No comment provided by engineer. */ "You can hide or mute a user profile - swipe it to the right." = "Możesz ukryć lub wyciszyć profil użytkownika - przesuń palcem w prawo."; +/* No comment provided by engineer. */ +"You can make it visible to your SimpleX contacts via Settings." = "Możesz ustawić go jako widoczny dla swoich kontaktów SimpleX w Ustawieniach."; + /* notification body */ "You can now send messages to %@" = "Możesz teraz wysyłać wiadomości do %@"; @@ -3833,6 +4001,9 @@ /* No comment provided by engineer. */ "You can use markdown to format messages:" = "Możesz używać markdown do formatowania wiadomości:"; +/* No comment provided by engineer. */ +"You can view invitation link again in connection details." = "Możesz zobaczyć link zaproszenia ponownie w szczegółach połączenia."; + /* No comment provided by engineer. */ "You can't send messages!" = "Nie możesz wysyłać wiadomości!"; @@ -3899,6 +4070,9 @@ /* chat list item description */ "you shared one-time link incognito" = "udostępniłeś jednorazowy link incognito"; +/* snd group event chat item */ +"you unblocked %@" = "odblokowałeś %@"; + /* No comment provided by engineer. */ "You will be connected to group when the group host's device is online, please wait or check later!" = "Zostaniesz połączony do grupy, gdy urządzenie gospodarza grupy będzie online, proszę czekać lub sprawdzić później!"; @@ -3959,9 +4133,6 @@ /* No comment provided by engineer. */ "Your contacts can allow full message deletion." = "Twoje kontakty mogą zezwolić na pełne usunięcie wiadomości."; -/* No comment provided by engineer. */ -"Your contacts in SimpleX will see it.\nYou can change it in Settings." = "Twoje kontakty w SimpleX będą to widzieć.\nMożesz to zmienić w Ustawieniach."; - /* No comment provided by engineer. */ "Your contacts will remain connected." = "Twoje kontakty pozostaną połączone."; diff --git a/apps/ios/ru.lproj/Localizable.strings b/apps/ios/ru.lproj/Localizable.strings index 03e4c4c508..871407ee3f 100644 --- a/apps/ios/ru.lproj/Localizable.strings +++ b/apps/ios/ru.lproj/Localizable.strings @@ -64,11 +64,14 @@ /* No comment provided by engineer. */ "[Star on GitHub](https://github.com/simplex-chat/simplex-chat)" = "[Поставить звездочку в GitHub](https://github.com/simplex-chat/simplex-chat)"; +/* No comment provided by engineer. */ +"**Add contact**: to create a new invitation link, or connect via a link you received." = "**Добавить контакт**: создать новую ссылку-приглашение или подключиться через полученную ссылку."; + /* No comment provided by engineer. */ "**Add new contact**: to create your one-time QR Code for your contact." = "**Добавить новый контакт**: чтобы создать одноразовый QR код или ссылку для Вашего контакта."; /* No comment provided by engineer. */ -"**Create link / QR code** for your contact to use." = "**Создать ссылку / QR код** для Вашего контакта."; +"**Create group**: to create a new group." = "**Создать группу**: создать новую группу."; /* No comment provided by engineer. */ "**e2e encrypted** audio call" = "**e2e зашифрованный** аудиозвонок"; @@ -82,18 +85,12 @@ /* No comment provided by engineer. */ "**Most private**: do not use SimpleX Chat notifications server, check messages periodically in the background (depends on how often you use the app)." = "**Самый конфиденциальный**: не использовать сервер уведомлений SimpleX Chat, проверять сообщения периодически в фоновом режиме (зависит от того насколько часто Вы используете приложение)."; -/* No comment provided by engineer. */ -"**Paste received link** or open it in the browser and tap **Open in mobile app**." = "**Вставить полученную ссылку**, или откройте её в браузере и нажмите **Open in mobile app**."; - /* No comment provided by engineer. */ "**Please note**: you will NOT be able to recover or change passphrase if you lose it." = "**Внимание**: Вы не сможете восстановить или поменять пароль, если Вы его потеряете."; /* No comment provided by engineer. */ "**Recommended**: device token and notifications are sent to SimpleX Chat notification server, but not the message content, size or who it is from." = "**Рекомендовано**: токен устройства и уведомления отправляются на сервер SimpleX Chat, но сервер не получает сами сообщения, их размер или от кого они."; -/* No comment provided by engineer. */ -"**Scan QR code**: to connect to your contact in person or via video call." = "**Сканировать QR код**: соединиться с Вашим контактом при встрече или во время видеозвонка."; - /* No comment provided by engineer. */ "**Warning**: Instant push notifications require passphrase saved in Keychain." = "**Внимание**: для работы мгновенных уведомлений пароль должен быть сохранен в Keychain."; @@ -205,6 +202,9 @@ /* No comment provided by engineer. */ "%lld messages blocked" = "%lld сообщений заблокировано"; +/* No comment provided by engineer. */ +"%lld messages blocked by admin" = "%lld сообщений заблокировано администратором"; + /* No comment provided by engineer. */ "%lld messages marked deleted" = "%lld сообщений помечено удалёнными"; @@ -280,9 +280,6 @@ /* time interval */ "1 week" = "1 неделю"; -/* No comment provided by engineer. */ -"1-time link" = "Одноразовая ссылка"; - /* No comment provided by engineer. */ "5 minutes" = "5 минут"; @@ -350,6 +347,9 @@ /* No comment provided by engineer. */ "Add address to your profile, so that your contacts can share it with other people. Profile update will be sent to your contacts." = "Добавьте адрес в свой профиль, чтобы Ваши контакты могли поделиться им. Профиль будет отправлен Вашим контактам."; +/* No comment provided by engineer. */ +"Add contact" = "Добавить контакт"; + /* No comment provided by engineer. */ "Add preset servers" = "Добавить серверы по умолчанию"; @@ -401,6 +401,9 @@ /* No comment provided by engineer. */ "All group members will remain connected." = "Все члены группы, которые соединились через эту ссылку, останутся в группе."; +/* No comment provided by engineer. */ +"All messages will be deleted - this cannot be undone!" = "Все сообщения будут удалены - это нельзя отменить!"; + /* No comment provided by engineer. */ "All messages will be deleted - this cannot be undone! The messages will be deleted ONLY for you." = "Все сообщения будут удалены - это действие нельзя отменить! Сообщения будут удалены только для Вас."; @@ -423,7 +426,7 @@ "Allow disappearing messages only if your contact allows it to you." = "Разрешить исчезающие сообщения, только если Ваш контакт разрешает их Вам."; /* No comment provided by engineer. */ -"Allow irreversible message deletion only if your contact allows it to you." = "Разрешить необратимое удаление сообщений, только если Ваш контакт разрешает это Вам."; +"Allow irreversible message deletion only if your contact allows it to you. (24 hours)" = "Разрешить необратимое удаление сообщений, только если Ваш контакт разрешает это Вам. (24 часа)"; /* No comment provided by engineer. */ "Allow message reactions only if your contact allows them." = "Разрешить реакции на сообщения, только если ваш контакт разрешает их."; @@ -438,7 +441,7 @@ "Allow sending disappearing messages." = "Разрешить посылать исчезающие сообщения."; /* No comment provided by engineer. */ -"Allow to irreversibly delete sent messages." = "Разрешить необратимо удалять отправленные сообщения."; +"Allow to irreversibly delete sent messages. (24 hours)" = "Разрешить необратимо удалять отправленные сообщения. (24 часа)"; /* No comment provided by engineer. */ "Allow to send files and media." = "Разрешить посылать файлы и медиа."; @@ -459,7 +462,7 @@ "Allow your contacts to call you." = "Разрешить Вашим контактам звонить Вам."; /* No comment provided by engineer. */ -"Allow your contacts to irreversibly delete sent messages." = "Разрешить Вашим контактам необратимо удалять отправленные сообщения."; +"Allow your contacts to irreversibly delete sent messages. (24 hours)" = "Разрешить Вашим контактам необратимо удалять отправленные сообщения. (24 часа)"; /* No comment provided by engineer. */ "Allow your contacts to send disappearing messages." = "Разрешить Вашим контактам отправлять исчезающие сообщения."; @@ -584,18 +587,33 @@ /* No comment provided by engineer. */ "Block" = "Заблокировать"; +/* No comment provided by engineer. */ +"Block for all" = "Заблокировать для всех"; + /* No comment provided by engineer. */ "Block group members" = "Блокируйте членов группы"; /* No comment provided by engineer. */ "Block member" = "Заблокировать члена группы"; +/* No comment provided by engineer. */ +"Block member for all?" = "Заблокировать члена для всех?"; + /* No comment provided by engineer. */ "Block member?" = "Заблокировать члена группы?"; /* No comment provided by engineer. */ "blocked" = "заблокировано"; +/* rcv group event chat item */ +"blocked %@" = "%@ заблокирован"; + +/* blocked chat item */ +"blocked by admin" = "заблокировано администратором"; + +/* No comment provided by engineer. */ +"Blocked by admin" = "Заблокирован администратором"; + /* No comment provided by engineer. */ "bold" = "жирный"; @@ -603,7 +621,7 @@ "Both you and your contact can add message reactions." = "И Вы, и Ваш контакт можете добавлять реакции на сообщения."; /* No comment provided by engineer. */ -"Both you and your contact can irreversibly delete sent messages." = "Вы и Ваш контакт можете необратимо удалять отправленные сообщения."; +"Both you and your contact can irreversibly delete sent messages. (24 hours)" = "Вы и Ваш контакт можете необратимо удалять отправленные сообщения. (24 часа)"; /* No comment provided by engineer. */ "Both you and your contact can make calls." = "Вы и Ваш контакт можете совершать звонки."; @@ -636,7 +654,7 @@ "Calls" = "Звонки"; /* No comment provided by engineer. */ -"Can't delete user profile!" = "Нельзя удалить профиль пользователя!"; +"Camera not available" = "Камера недоступна"; /* No comment provided by engineer. */ "Can't invite contact!" = "Нельзя пригласить контакт!"; @@ -723,6 +741,9 @@ /* No comment provided by engineer. */ "Chat is stopped" = "Чат остановлен"; +/* No comment provided by engineer. */ +"Chat is stopped. If you already used this database on another device, you should transfer it back before starting chat." = "Чат остановлен. Если вы уже использовали эту базу данных на другом устройстве, перенесите ее обратно до запуска чата."; + /* No comment provided by engineer. */ "Chat preferences" = "Предпочтения"; @@ -750,6 +771,9 @@ /* No comment provided by engineer. */ "Clear conversation?" = "Очистить разговор?"; +/* No comment provided by engineer. */ +"Clear private notes?" = "Очистить личные заметки?"; + /* No comment provided by engineer. */ "Clear verification" = "Сбросить подтверждение"; @@ -816,9 +840,6 @@ /* No comment provided by engineer. */ "Connect via link" = "Соединиться через ссылку"; -/* No comment provided by engineer. */ -"Connect via link / QR code" = "Соединиться через ссылку / QR код"; - /* No comment provided by engineer. */ "Connect via one-time link" = "Соединиться через одноразовую ссылку"; @@ -891,6 +912,9 @@ /* connection information */ "connection:%@" = "connection:%@"; +/* profile update event chat item */ +"contact %@ changed to %@" = "контакт %1$@ изменён на %2$@"; + /* No comment provided by engineer. */ "Contact allows" = "Контакт разрешает"; @@ -960,9 +984,6 @@ /* No comment provided by engineer. */ "Create new profile in [desktop app](https://simplex.chat/downloads/). 💻" = "Создайте новый профиль в [приложении для компьютера](https://simplex.chat/downloads/). 💻"; -/* No comment provided by engineer. */ -"Create one-time invitation link" = "Создать ссылку-приглашение"; - /* No comment provided by engineer. */ "Create profile" = "Создать профиль"; @@ -978,9 +999,18 @@ /* No comment provided by engineer. */ "Create your profile" = "Создать профиль"; +/* No comment provided by engineer. */ +"Created at" = "Создано"; + +/* copied message info */ +"Created at: %@" = "Создано: %@"; + /* No comment provided by engineer. */ "Created on %@" = "Дата создания %@"; +/* No comment provided by engineer. */ +"Creating link…" = "Создаётся ссылка…"; + /* No comment provided by engineer. */ "creator" = "создатель"; @@ -1299,6 +1329,9 @@ /* No comment provided by engineer. */ "Do it later" = "Отложить"; +/* No comment provided by engineer. */ +"Do not send history to new members." = "Не отправлять историю новым членам."; + /* No comment provided by engineer. */ "Do NOT use SimpleX for emergency calls." = "Не используйте SimpleX для экстренных звонков."; @@ -1344,6 +1377,9 @@ /* No comment provided by engineer. */ "Enable automatic message deletion?" = "Включить автоматическое удаление сообщений?"; +/* No comment provided by engineer. */ +"Enable camera access" = "Включить доступ к камере"; + /* No comment provided by engineer. */ "Enable for all" = "Включить для всех"; @@ -1398,6 +1434,9 @@ /* notification */ "Encrypted message or another event" = "Зашифрованное сообщение или событие чата"; +/* notification */ +"Encrypted message: app is stopped" = "Зашифрованное сообщение: приложение остановлено"; + /* notification */ "Encrypted message: database error" = "Зашифрованное сообщение: ошибка базы данных"; @@ -1518,6 +1557,9 @@ /* No comment provided by engineer. */ "Error creating member contact" = "Ошибка создания контакта с членом группы"; +/* No comment provided by engineer. */ +"Error creating message" = "Ошибка создания сообщения"; + /* No comment provided by engineer. */ "Error creating profile!" = "Ошибка создания профиля!"; @@ -1569,6 +1611,9 @@ /* No comment provided by engineer. */ "Error loading %@ servers" = "Ошибка загрузки %@ серверов"; +/* No comment provided by engineer. */ +"Error opening chat" = "Ошибка доступа к чату"; + /* No comment provided by engineer. */ "Error receiving file" = "Ошибка при получении файла"; @@ -1593,6 +1638,9 @@ /* No comment provided by engineer. */ "Error saving user password" = "Ошибка при сохранении пароля пользователя"; +/* No comment provided by engineer. */ +"Error scanning code: %@" = "Ошибка сканирования кода: %@"; + /* No comment provided by engineer. */ "Error sending email" = "Ошибка отправки email"; @@ -1798,7 +1846,7 @@ "Group members can add message reactions." = "Члены группы могут добавлять реакции на сообщения."; /* No comment provided by engineer. */ -"Group members can irreversibly delete sent messages." = "Члены группы могут необратимо удалять отправленные сообщения."; +"Group members can irreversibly delete sent messages. (24 hours)" = "Члены группы могут необратимо удалять отправленные сообщения. (24 часа)"; /* No comment provided by engineer. */ "Group members can send direct messages." = "Члены группы могут посылать прямые сообщения."; @@ -1866,6 +1914,9 @@ /* No comment provided by engineer. */ "History" = "История"; +/* No comment provided by engineer. */ +"History is not sent to new members." = "История не отправляется новым членам."; + /* time unit */ "hours" = "часов"; @@ -1890,9 +1941,6 @@ /* No comment provided by engineer. */ "If you can't meet in person, show QR code in a video call, or share the link." = "Если Вы не можете встретиться лично, покажите QR-код во время видеозвонка или поделитесь ссылкой."; -/* No comment provided by engineer. */ -"If you cannot meet in person, you can **scan QR code in the video call**, or your contact can share an invitation link." = "Если Вы не можете встретиться лично, Вы можете **сосканировать QR код во время видеозвонка**, или Ваш контакт может отправить Вам ссылку."; - /* No comment provided by engineer. */ "If you enter this passcode when opening the app, all app data will be irreversibly removed!" = "Если Вы введете этот код при открытии приложения, все данные приложения будут безвозвратно удалены!"; @@ -1926,6 +1974,9 @@ /* No comment provided by engineer. */ "Import database" = "Импорт архива чата"; +/* No comment provided by engineer. */ +"Improved message delivery" = "Улучшенная доставка сообщений"; + /* No comment provided by engineer. */ "Improved privacy and security" = "Улучшенная безопасность"; @@ -2010,9 +2061,21 @@ /* invalid chat item */ "invalid data" = "ошибка данных"; +/* No comment provided by engineer. */ +"Invalid display name!" = "Ошибка имени!"; + +/* No comment provided by engineer. */ +"Invalid link" = "Ошибка ссылки"; + /* No comment provided by engineer. */ "Invalid name!" = "Неверное имя!"; +/* No comment provided by engineer. */ +"Invalid QR code" = "Неверный QR код"; + +/* No comment provided by engineer. */ +"Invalid response" = "Ошибка ответа"; + /* No comment provided by engineer. */ "Invalid server address!" = "Ошибка в адресе сервера!"; @@ -2091,6 +2154,9 @@ /* No comment provided by engineer. */ "Join group" = "Вступить в группу"; +/* No comment provided by engineer. */ +"Join group conversations" = "Присоединяйтесь к разговорам в группах"; + /* No comment provided by engineer. */ "Join group?" = "Вступить в группу?"; @@ -2106,9 +2172,15 @@ /* No comment provided by engineer. */ "Joining group" = "Вступление в группу"; +/* No comment provided by engineer. */ +"Keep" = "Оставить"; + /* No comment provided by engineer. */ "Keep the app open to use it from desktop" = "Оставьте приложение открытым, чтобы использовать его с компьютера"; +/* No comment provided by engineer. */ +"Keep unused invitation?" = "Оставить неиспользованное приглашение?"; + /* No comment provided by engineer. */ "Keep your connections" = "Сохраните Ваши соединения"; @@ -2163,6 +2235,9 @@ /* No comment provided by engineer. */ "Live messages" = "\"Живые\" сообщения"; +/* No comment provided by engineer. */ +"Local" = "Локальные"; + /* No comment provided by engineer. */ "Local name" = "Локальное имя"; @@ -2217,6 +2292,9 @@ /* No comment provided by engineer. */ "Member" = "Член группы"; +/* profile update event chat item */ +"member %@ changed to %@" = "член %1$@ изменился на %2$@"; + /* rcv group event chat item */ "member connected" = "соединен(а)"; @@ -2334,6 +2412,9 @@ /* No comment provided by engineer. */ "never" = "никогда"; +/* No comment provided by engineer. */ +"New chat" = "Новый чат"; + /* notification */ "New contact request" = "Новый запрос на соединение"; @@ -2432,9 +2513,6 @@ /* No comment provided by engineer. */ "Off" = "Выключено"; -/* No comment provided by engineer. */ -"Off (Local)" = "Выключить (Локальные)"; - /* feature offered item */ "offered %@" = "предложил(a) %@"; @@ -2444,6 +2522,9 @@ /* No comment provided by engineer. */ "Ok" = "Ок"; +/* No comment provided by engineer. */ +"OK" = "OK"; + /* No comment provided by engineer. */ "Old database" = "Предыдущая версия данных чата"; @@ -2481,7 +2562,7 @@ "Only you can add message reactions." = "Только Вы можете добавлять реакции на сообщения."; /* No comment provided by engineer. */ -"Only you can irreversibly delete messages (your contact can mark them for deletion)." = "Только Вы можете необратимо удалять сообщения (Ваш контакт может помечать их на удаление)."; +"Only you can irreversibly delete messages (your contact can mark them for deletion). (24 hours)" = "Только Вы можете необратимо удалять сообщения (Ваш контакт может помечать их на удаление). (24 часа)"; /* No comment provided by engineer. */ "Only you can make calls." = "Только Вы можете совершать звонки."; @@ -2496,7 +2577,7 @@ "Only your contact can add message reactions." = "Только Ваш контакт может добавлять реакции на сообщения."; /* No comment provided by engineer. */ -"Only your contact can irreversibly delete messages (you can mark them for deletion)." = "Только Ваш контакт может необратимо удалять сообщения (Вы можете помечать их на удаление)."; +"Only your contact can irreversibly delete messages (you can mark them for deletion). (24 hours)" = "Только Ваш контакт может необратимо удалять сообщения (Вы можете помечать их на удаление). (24 часа)"; /* No comment provided by engineer. */ "Only your contact can make calls." = "Только Ваш контакт может совершать звонки."; @@ -2529,7 +2610,13 @@ "Open-source protocol and code – anybody can run the servers." = "Открытый протокол и код - кто угодно может запустить сервер."; /* No comment provided by engineer. */ -"Opening database…" = "Открытие базы данных…"; +"Opening app…" = "Приложение отрывается…"; + +/* No comment provided by engineer. */ +"Or scan QR code" = "Или отсканируйте QR код"; + +/* No comment provided by engineer. */ +"Or show this code" = "Или покажите этот код"; /* member role */ "owner" = "владелец"; @@ -2552,8 +2639,8 @@ /* No comment provided by engineer. */ "Password to show" = "Пароль чтобы раскрыть"; -/* No comment provided by engineer. */ -"Paste" = "Вставить"; +/* past/unknown group member */ +"Past member %@" = "Бывший член %@"; /* No comment provided by engineer. */ "Paste desktop address" = "Вставить адрес компьютера"; @@ -2562,10 +2649,10 @@ "Paste image" = "Вставить изображение"; /* No comment provided by engineer. */ -"Paste received link" = "Вставить полученную ссылку"; +"Paste link to connect!" = "Вставьте ссылку, чтобы соединиться!"; -/* placeholder */ -"Paste the link you received to connect with your contact." = "Чтобы соединиться, вставьте ссылку, полученную от Вашего контакта."; +/* No comment provided by engineer. */ +"Paste the link you received" = "Вставьте полученную ссылку"; /* No comment provided by engineer. */ "peer-to-peer" = "peer-to-peer"; @@ -2597,6 +2684,9 @@ /* No comment provided by engineer. */ "Please check yours and your contact preferences." = "Проверьте предпочтения Вашего контакта."; +/* No comment provided by engineer. */ +"Please contact developers.\nError: %@" = "Пожалуйста, сообщите разработчикам.\nОшибка: %@"; + /* No comment provided by engineer. */ "Please contact group admin." = "Пожалуйста, свяжитесь с админом группы."; @@ -2648,6 +2738,9 @@ /* No comment provided by engineer. */ "Private filenames" = "Защищенные имена файлов"; +/* name of notes to self */ +"Private notes" = "Личные заметки"; + /* No comment provided by engineer. */ "Profile and server connections" = "Профиль и соединения на сервере"; @@ -2720,6 +2813,9 @@ /* No comment provided by engineer. */ "Read more in [User Guide](https://simplex.chat/docs/guide/app-settings.html#your-simplex-contact-address)." = "Узнать больше в [Руководстве пользователя](https://simplex.chat/docs/guide/app-settings.html#your-simplex-contact-address)."; +/* No comment provided by engineer. */ +"Read more in [User Guide](https://simplex.chat/docs/guide/chat-profiles.html#incognito-mode)." = "Дополнительная информация в [Руководстве пользователя](https://simplex.chat/docs/guide/chat-profiles.html#incognito-mode)."; + /* No comment provided by engineer. */ "Read more in [User Guide](https://simplex.chat/docs/guide/readme.html#connect-to-friends)." = "Узнать больше в [Руководстве пользователя](https://simplex.chat/docs/guide/readme.html#connect-to-friends)."; @@ -2759,6 +2855,9 @@ /* No comment provided by engineer. */ "Receiving via" = "Получение через"; +/* No comment provided by engineer. */ +"Recent history and improved [directory bot](simplex:/contact#/?v=1-4&smp=smp%3A%2F%2Fu2dS9sG8nMNURyZwqASV4yROM28Er0luVTx5X1CsMrU%3D%40smp4.simplex.im%2FeXSPwqTkKyDO3px4fLf1wx3MvPdjdLW3%23%2F%3Fv%3D1-2%26dh%3DMCowBQYDK2VuAyEAaiv6MkMH44L2TcYrt_CsX3ZvM11WgbMEUn0hkIKTOho%253D%26srv%3Do5vmywmrnaxalvz6wi3zicyftgio6psuvyniis6gco6bp6ekl4cqj4id.onion)." = "История сообщений и улучшенный [каталог групп](simplex:/contact#/?v=1-4&smp=smp%3A%2F%2Fu2dS9sG8nMNURyZwqASV4yROM28Er0luVTx5X1CsMrU%3D%40smp4.simplex.im%2FeXSPwqTkKyDO3px4fLf1wx3MvPdjdLW3%23%2F%3Fv%3D1-2%26dh%3DMCowBQYDK2VuAyEAaiv6MkMH44L2TcYrt_CsX3ZvM11WgbMEUn0hkIKTOho%253D%26srv%3Do5vmywmrnaxalvz6wi3zicyftgio6psuvyniis6gco6bp6ekl4cqj4id.onion)."; + /* No comment provided by engineer. */ "Recipients see updates as you type them." = "Получатели видят их в то время как Вы их набираете."; @@ -2813,6 +2912,12 @@ /* rcv group event chat item */ "removed %@" = "удалил(а) %@"; +/* profile update event chat item */ +"removed contact address" = "удалён адрес контакта"; + +/* profile update event chat item */ +"removed profile picture" = "удалена картинка профиля"; + /* rcv group event chat item */ "removed you" = "удалил(а) Вас из группы"; @@ -2864,6 +2969,9 @@ /* No comment provided by engineer. */ "Restore database error" = "Ошибка при восстановлении базы данных"; +/* No comment provided by engineer. */ +"Retry" = "Повторить"; + /* chat item action */ "Reveal" = "Показать"; @@ -2933,6 +3041,9 @@ /* No comment provided by engineer. */ "Save welcome message?" = "Сохранить приветственное сообщение?"; +/* message info title */ +"Saved message" = "Сохраненное сообщение"; + /* No comment provided by engineer. */ "Saved WebRTC ICE servers will be removed" = "Сохраненные WebRTC ICE серверы будут удалены"; @@ -2954,6 +3065,12 @@ /* No comment provided by engineer. */ "Search" = "Поиск"; +/* No comment provided by engineer. */ +"Search bar accepts invitation links." = "Поле поиска поддерживает ссылки-приглашения."; + +/* No comment provided by engineer. */ +"Search or paste SimpleX link" = "Искать или вставьте ссылку SimpleX"; + /* network option */ "sec" = "сек"; @@ -3032,6 +3149,9 @@ /* No comment provided by engineer. */ "Send them from gallery or custom keyboards." = "Отправьте из галереи или из дополнительных клавиатур."; +/* No comment provided by engineer. */ +"Send up to 100 last messages to new members." = "Отправить до 100 последних сообщений новым членам."; + /* No comment provided by engineer. */ "Sender cancelled file transfer." = "Отправитель отменил передачу файла."; @@ -3104,6 +3224,12 @@ /* No comment provided by engineer. */ "Set it instead of system authentication." = "Установите код вместо системной аутентификации."; +/* profile update event chat item */ +"set new contact address" = "установлен новый адрес контакта"; + +/* profile update event chat item */ +"set new profile picture" = "установлена новая картинка профиля"; + /* No comment provided by engineer. */ "Set passcode" = "Установить код доступа"; @@ -3135,7 +3261,7 @@ "Share link" = "Поделиться ссылкой"; /* No comment provided by engineer. */ -"Share one-time invitation link" = "Поделиться ссылкой-приглашением"; +"Share this 1-time invite link" = "Поделиться одноразовой ссылкой-приглашением"; /* No comment provided by engineer. */ "Share with contacts" = "Поделиться с контактами"; @@ -3213,10 +3339,10 @@ "Somebody" = "Контакт"; /* No comment provided by engineer. */ -"Start a new chat" = "Начать новый разговор"; +"Start chat" = "Запустить чат"; /* No comment provided by engineer. */ -"Start chat" = "Запустить чат"; +"Start chat?" = "Запустить чат?"; /* No comment provided by engineer. */ "Start migration" = "Запустить перемещение данных"; @@ -3287,6 +3413,12 @@ /* No comment provided by engineer. */ "Tap to join incognito" = "Нажмите, чтобы вступить инкогнито"; +/* No comment provided by engineer. */ +"Tap to paste link" = "Нажмите, чтобы вставить ссылку"; + +/* No comment provided by engineer. */ +"Tap to scan" = "Нажмите, чтобы сканировать"; + /* No comment provided by engineer. */ "Tap to start a new chat" = "Нажмите, чтобы начать чат"; @@ -3332,6 +3464,9 @@ /* No comment provided by engineer. */ "The attempt to change database passphrase was not completed." = "Попытка поменять пароль базы данных не была завершена."; +/* No comment provided by engineer. */ +"The code you scanned is not a SimpleX link QR code." = "Этот QR код не является SimpleX-ccылкой."; + /* No comment provided by engineer. */ "The connection you accepted will be cancelled!" = "Подтвержденное соединение будет отменено!"; @@ -3374,15 +3509,12 @@ /* No comment provided by engineer. */ "The servers for new connections of your current chat profile **%@**." = "Серверы для новых соединений Вашего текущего профиля чата **%@**."; +/* No comment provided by engineer. */ +"The text you pasted is not a SimpleX link." = "Вставленный текст не является SimpleX-ссылкой."; + /* No comment provided by engineer. */ "Theme" = "Тема"; -/* No comment provided by engineer. */ -"There should be at least one user profile." = "Должен быть хотя бы один профиль пользователя."; - -/* No comment provided by engineer. */ -"There should be at least one visible user profile." = "Должен быть хотя бы один открытый профиль пользователя."; - /* No comment provided by engineer. */ "These settings are for your current profile **%@**." = "Установки для Вашего активного профиля **%@**."; @@ -3404,6 +3536,9 @@ /* No comment provided by engineer. */ "This device name" = "Имя этого устройства"; +/* No comment provided by engineer. */ +"This display name is invalid. Please choose another name." = "Ошибка имени профиля. Пожалуйста, выберите другое имя."; + /* No comment provided by engineer. */ "This group has over %lld members, delivery receipts are not sent." = "В группе более %lld членов, отчёты о доставке выключены."; @@ -3465,10 +3600,10 @@ "Trying to connect to the server used to receive messages from this contact." = "Устанавливается соединение с сервером, через который Вы получаете сообщения от этого контакта."; /* No comment provided by engineer. */ -"Turn off" = "Выключить"; +"Turkish interface" = "Турецкий интерфейс"; /* No comment provided by engineer. */ -"Turn off notifications?" = "Выключить уведомления?"; +"Turn off" = "Выключить"; /* No comment provided by engineer. */ "Turn on" = "Включить"; @@ -3479,12 +3614,21 @@ /* No comment provided by engineer. */ "Unblock" = "Разблокировать"; +/* No comment provided by engineer. */ +"Unblock for all" = "Разблокировать для всех"; + /* No comment provided by engineer. */ "Unblock member" = "Разблокировать члена группы"; +/* No comment provided by engineer. */ +"Unblock member for all?" = "Разблокировать члена для всех?"; + /* No comment provided by engineer. */ "Unblock member?" = "Разблокировать члена группы?"; +/* rcv group event chat item */ +"unblocked %@" = "%@ разблокирован"; + /* item status description */ "Unexpected error: %@" = "Неожиданная ошибка: %@"; @@ -3518,6 +3662,9 @@ /* No comment provided by engineer. */ "Unknown error" = "Неизвестная ошибка"; +/* No comment provided by engineer. */ +"unknown status" = "неизвестный статус"; + /* No comment provided by engineer. */ "Unless you use iOS call interface, enable Do Not Disturb mode to avoid interruptions." = "Если Вы не используете интерфейс iOS, включите режим Не отвлекать, чтобы звонок не прерывался."; @@ -3542,6 +3689,9 @@ /* No comment provided by engineer. */ "Unread" = "Не прочитано"; +/* No comment provided by engineer. */ +"Up to 100 last messages are sent to new members." = "До 100 последних сообщений отправляются новым членам."; + /* No comment provided by engineer. */ "Update" = "Обновить"; @@ -3560,6 +3710,9 @@ /* rcv group event chat item */ "updated group profile" = "обновил(а) профиль группы"; +/* profile update event chat item */ +"updated profile" = "профиль обновлён"; + /* No comment provided by engineer. */ "Updating settings will re-connect the client to all servers." = "Обновление настроек приведет к сбросу и установке нового соединения со всеми серверами."; @@ -3593,6 +3746,9 @@ /* No comment provided by engineer. */ "Use new incognito profile" = "Использовать новый Инкогнито профиль"; +/* No comment provided by engineer. */ +"Use only local notifications?" = "Использовать только локальные нотификации?"; + /* No comment provided by engineer. */ "Use server" = "Использовать сервер"; @@ -3665,6 +3821,9 @@ /* No comment provided by engineer. */ "View security code" = "Показать код безопасности"; +/* chat feature */ +"Visible history" = "Доступ к истории"; + /* No comment provided by engineer. */ "Voice message…" = "Голосовое сообщение…"; @@ -3728,9 +3887,15 @@ /* No comment provided by engineer. */ "When you share an incognito profile with somebody, this profile will be used for the groups they invite you to." = "Когда Вы соединены с контактом инкогнито, тот же самый инкогнито профиль будет использоваться для групп с этим контактом."; +/* No comment provided by engineer. */ +"With encrypted files and media." = "С зашифрованными файлами и медиа."; + /* No comment provided by engineer. */ "With optional welcome message." = "С опциональным авто-ответом."; +/* No comment provided by engineer. */ +"With reduced battery usage." = "С уменьшенным потреблением батареи."; + /* No comment provided by engineer. */ "Wrong database passphrase" = "Неправильный пароль базы данных"; @@ -3791,11 +3956,11 @@ /* No comment provided by engineer. */ "you are observer" = "только чтение сообщений"; -/* No comment provided by engineer. */ -"You can accept calls from lock screen, without device and app authentication." = "Вы можете принимать звонки на экране блокировки, без аутентификации."; +/* snd group event chat item */ +"you blocked %@" = "Вы заблокировали %@"; /* No comment provided by engineer. */ -"You can also connect by clicking the link. If it opens in the browser, click **Open in mobile app** button." = "Вы также можете соединиться, открыв ссылку. Если ссылка откроется в браузере, нажмите кнопку **Open in mobile app**."; +"You can accept calls from lock screen, without device and app authentication." = "Вы можете принимать звонки на экране блокировки, без аутентификации."; /* No comment provided by engineer. */ "You can create it later" = "Вы можете создать его позже"; @@ -3809,6 +3974,9 @@ /* No comment provided by engineer. */ "You can hide or mute a user profile - swipe it to the right." = "Вы можете скрыть профиль или выключить уведомления - потяните его вправо."; +/* No comment provided by engineer. */ +"You can make it visible to your SimpleX contacts via Settings." = "Вы можете сделать его видимым для ваших контактов в SimpleX через Настройки."; + /* notification body */ "You can now send messages to %@" = "Вы теперь можете отправлять сообщения %@"; @@ -3833,6 +4001,9 @@ /* No comment provided by engineer. */ "You can use markdown to format messages:" = "Вы можете форматировать сообщения:"; +/* No comment provided by engineer. */ +"You can view invitation link again in connection details." = "Вы можете увидеть ссылку-приглашение снова открыв соединение."; + /* No comment provided by engineer. */ "You can't send messages!" = "Вы не можете отправлять сообщения!"; @@ -3899,6 +4070,9 @@ /* chat list item description */ "you shared one-time link incognito" = "Вы создали ссылку инкогнито"; +/* snd group event chat item */ +"you unblocked %@" = "Вы разблокировали %@"; + /* No comment provided by engineer. */ "You will be connected to group when the group host's device is online, please wait or check later!" = "Соединение с группой будет установлено, когда хост группы будет онлайн. Пожалуйста, подождите или проверьте позже!"; @@ -3959,9 +4133,6 @@ /* No comment provided by engineer. */ "Your contacts can allow full message deletion." = "Ваши контакты могут разрешить окончательное удаление сообщений."; -/* No comment provided by engineer. */ -"Your contacts in SimpleX will see it.\nYou can change it in Settings." = "Ваши контакты в SimpleX получат этот адрес.\nВы можете изменить это в Настройках."; - /* No comment provided by engineer. */ "Your contacts will remain connected." = "Ваши контакты сохранятся."; diff --git a/apps/ios/th.lproj/Localizable.strings b/apps/ios/th.lproj/Localizable.strings index eb47218422..686c1a58a0 100644 --- a/apps/ios/th.lproj/Localizable.strings +++ b/apps/ios/th.lproj/Localizable.strings @@ -55,9 +55,6 @@ /* No comment provided by engineer. */ "**Add new contact**: to create your one-time QR Code for your contact." = "**เพิ่มผู้ติดต่อใหม่**: เพื่อสร้างคิวอาร์โค้ดแบบใช้ครั้งเดียวหรือลิงก์สำหรับผู้ติดต่อของคุณ"; -/* No comment provided by engineer. */ -"**Create link / QR code** for your contact to use." = "**สร้างลิงค์ / คิวอาร์โค้ด** เพื่อให้ผู้ติดต่อของคุณใช้"; - /* No comment provided by engineer. */ "**e2e encrypted** audio call" = "การโทรเสียงแบบ **encrypted จากต้นจนจบ**"; @@ -70,18 +67,12 @@ /* No comment provided by engineer. */ "**Most private**: do not use SimpleX Chat notifications server, check messages periodically in the background (depends on how often you use the app)." = "**ส่วนตัวที่สุด**: ไม่ใช้เซิร์ฟเวอร์การแจ้งเตือนของ SimpleX Chat ตรวจสอบข้อความเป็นระยะในพื้นหลัง (ขึ้นอยู่กับความถี่ที่คุณใช้แอป)"; -/* No comment provided by engineer. */ -"**Paste received link** or open it in the browser and tap **Open in mobile app**." = "**แปะลิงก์ที่ได้รับ** หรือเปิดในเบราว์เซอร์แล้วแตะ **เปิดในแอปมือถือ**"; - /* No comment provided by engineer. */ "**Please note**: you will NOT be able to recover or change passphrase if you lose it." = "**โปรดทราบ**: คุณจะไม่สามารถกู้คืนหรือเปลี่ยนรหัสผ่านได้หากคุณทำรหัสผ่านหาย"; /* No comment provided by engineer. */ "**Recommended**: device token and notifications are sent to SimpleX Chat notification server, but not the message content, size or who it is from." = "**แนะนำ**: โทเค็นอุปกรณ์และการแจ้งเตือนจะถูกส่งไปยังเซิร์ฟเวอร์การแจ้งเตือนของ SimpleX Chat แต่ไม่ใช่เนื้อหาข้อความ ขนาด หรือผู้ที่ส่ง"; -/* No comment provided by engineer. */ -"**Scan QR code**: to connect to your contact in person or via video call." = "**สแกนคิวอาร์โค้ด**: เพื่อเชื่อมต่อกับผู้ติดต่อของคุณด้วยตนเองหรือผ่านการสนทนาทางวิดีโอ"; - /* No comment provided by engineer. */ "**Warning**: Instant push notifications require passphrase saved in Keychain." = "**คำเตือน**: การแจ้งเตือนแบบพุชทันทีจำเป็นต้องบันทึกรหัสผ่านไว้ใน Keychain"; @@ -226,9 +217,6 @@ /* time interval */ "1 week" = "1 สัปดาห์"; -/* No comment provided by engineer. */ -"1-time link" = "ลิงก์สำหรับใช้ 1 ครั้ง"; - /* No comment provided by engineer. */ "5 minutes" = "5 นาที"; @@ -360,7 +348,7 @@ "Allow disappearing messages only if your contact allows it to you." = "อนุญาตให้ข้อความที่หายไปเฉพาะในกรณีที่ผู้ติดต่อของคุณอนุญาตเท่านั้น."; /* No comment provided by engineer. */ -"Allow irreversible message deletion only if your contact allows it to you." = "อนุญาตให้ลบข้อความแบบถาวรเฉพาะในกรณีที่ผู้ติดต่อของคุณอนุญาตให้คุณเท่านั้น"; +"Allow irreversible message deletion only if your contact allows it to you. (24 hours)" = "อนุญาตให้ลบข้อความแบบถาวรเฉพาะในกรณีที่ผู้ติดต่อของคุณอนุญาตให้คุณเท่านั้น"; /* No comment provided by engineer. */ "Allow message reactions only if your contact allows them." = "อนุญาตการแสดงปฏิกิริยาต่อข้อความเฉพาะเมื่อผู้ติดต่อของคุณอนุญาตเท่านั้น"; @@ -375,7 +363,7 @@ "Allow sending disappearing messages." = "อนุญาตให้ส่งข้อความที่จะหายไปหลังปิดแชท (disappearing message)"; /* No comment provided by engineer. */ -"Allow to irreversibly delete sent messages." = "อนุญาตให้ลบข้อความที่ส่งไปแล้วอย่างถาวร"; +"Allow to irreversibly delete sent messages. (24 hours)" = "อนุญาตให้ลบข้อความที่ส่งไปแล้วอย่างถาวร"; /* No comment provided by engineer. */ "Allow to send files and media." = "อนุญาตให้ส่งไฟล์และสื่อ"; @@ -396,7 +384,7 @@ "Allow your contacts to call you." = "อนุญาตให้ผู้ติดต่อของคุณโทรหาคุณ"; /* No comment provided by engineer. */ -"Allow your contacts to irreversibly delete sent messages." = "อนุญาตให้ผู้ติดต่อของคุณลบข้อความที่ส่งแล้วอย่างถาวร"; +"Allow your contacts to irreversibly delete sent messages. (24 hours)" = "อนุญาตให้ผู้ติดต่อของคุณลบข้อความที่ส่งแล้วอย่างถาวร"; /* No comment provided by engineer. */ "Allow your contacts to send disappearing messages." = "อนุญาตให้ผู้ติดต่อของคุณส่งข้อความที่จะหายไปหลังปิดแชท (disappearing messages)"; @@ -504,7 +492,7 @@ "Both you and your contact can add message reactions." = "ทั้งคุณและผู้ติดต่อของคุณสามารถเพิ่มปฏิกิริยาของข้อความได้"; /* No comment provided by engineer. */ -"Both you and your contact can irreversibly delete sent messages." = "ทั้งคุณและผู้ติดต่อของคุณสามารถลบข้อความที่ส่งแล้วอย่างถาวรได้"; +"Both you and your contact can irreversibly delete sent messages. (24 hours)" = "ทั้งคุณและผู้ติดต่อของคุณสามารถลบข้อความที่ส่งแล้วอย่างถาวรได้"; /* No comment provided by engineer. */ "Both you and your contact can make calls." = "ทั้งคุณและผู้ติดต่อของคุณสามารถโทรออกได้"; @@ -533,9 +521,6 @@ /* No comment provided by engineer. */ "Calls" = "โทร"; -/* No comment provided by engineer. */ -"Can't delete user profile!" = "ไม่สามารถลบโปรไฟล์ผู้ใช้ได้!"; - /* No comment provided by engineer. */ "Can't invite contact!" = "ไม่สามารถเชิญผู้ติดต่อได้!"; @@ -693,9 +678,6 @@ /* No comment provided by engineer. */ "Connect via link" = "เชื่อมต่อผ่านลิงก์"; -/* No comment provided by engineer. */ -"Connect via link / QR code" = "เชื่อมต่อผ่านลิงค์ / คิวอาร์โค้ด"; - /* No comment provided by engineer. */ "connected" = "เชื่อมต่อสำเร็จ"; @@ -804,9 +786,6 @@ /* No comment provided by engineer. */ "Create link" = "สร้างลิงค์"; -/* No comment provided by engineer. */ -"Create one-time invitation link" = "สร้างลิงก์เชิญแบบใช้ครั้งเดียว"; - /* server test step */ "Create queue" = "สร้างคิว"; @@ -1552,7 +1531,7 @@ "Group members can add message reactions." = "สมาชิกกลุ่มสามารถเพิ่มการแสดงปฏิกิริยาต่อข้อความได้"; /* No comment provided by engineer. */ -"Group members can irreversibly delete sent messages." = "สมาชิกกลุ่มสามารถลบข้อความที่ส่งแล้วอย่างถาวร"; +"Group members can irreversibly delete sent messages. (24 hours)" = "สมาชิกกลุ่มสามารถลบข้อความที่ส่งแล้วอย่างถาวร"; /* No comment provided by engineer. */ "Group members can send direct messages." = "สมาชิกกลุ่มสามารถส่งข้อความโดยตรงได้"; @@ -1644,9 +1623,6 @@ /* No comment provided by engineer. */ "If you can't meet in person, show QR code in a video call, or share the link." = "หากคุณไม่สามารถพบกันในชีวิตจริงได้ ให้แสดงคิวอาร์โค้ดในวิดีโอคอล หรือแชร์ลิงก์"; -/* No comment provided by engineer. */ -"If you cannot meet in person, you can **scan QR code in the video call**, or your contact can share an invitation link." = "หากคุณไม่สามารถพบปะด้วยตนเอง คุณสามารถ **สแกนคิวอาร์โค้ดผ่านการสนทนาทางวิดีโอ** หรือผู้ติดต่อของคุณสามารถแชร์ลิงก์เชิญได้"; - /* No comment provided by engineer. */ "If you enter this passcode when opening the app, all app data will be irreversibly removed!" = "หากคุณใส่รหัสผ่านนี้เมื่อเปิดแอป ข้อมูลแอปทั้งหมดจะถูกลบอย่างถาวร!"; @@ -1881,6 +1857,9 @@ /* No comment provided by engineer. */ "Live messages" = "ข้อความสด"; +/* No comment provided by engineer. */ +"Local" = "ในเครื่อง"; + /* No comment provided by engineer. */ "Local name" = "ชื่อภายในเครื่องเท่านั้น"; @@ -2135,9 +2114,6 @@ /* No comment provided by engineer. */ "Off" = "ปิด"; -/* No comment provided by engineer. */ -"Off (Local)" = "ปิด (ในเครื่อง)"; - /* feature offered item */ "offered %@" = "เสนอแล้ว %@"; @@ -2184,7 +2160,7 @@ "Only you can add message reactions." = "มีเพียงคุณเท่านั้นที่สามารถแสดงปฏิกิริยาต่อข้อความได้"; /* No comment provided by engineer. */ -"Only you can irreversibly delete messages (your contact can mark them for deletion)." = "มีเพียงคุณเท่านั้นที่สามารถลบข้อความแบบย้อนกลับไม่ได้ (ผู้ติดต่อของคุณสามารถทำเครื่องหมายเพื่อลบได้)"; +"Only you can irreversibly delete messages (your contact can mark them for deletion). (24 hours)" = "มีเพียงคุณเท่านั้นที่สามารถลบข้อความแบบย้อนกลับไม่ได้ (ผู้ติดต่อของคุณสามารถทำเครื่องหมายเพื่อลบได้)"; /* No comment provided by engineer. */ "Only you can make calls." = "มีเพียงคุณเท่านั้นที่โทรออกได้"; @@ -2199,7 +2175,7 @@ "Only your contact can add message reactions." = "เฉพาะผู้ติดต่อของคุณเท่านั้นที่สามารถเพิ่มการโต้ตอบข้อความได้"; /* No comment provided by engineer. */ -"Only your contact can irreversibly delete messages (you can mark them for deletion)." = "เฉพาะผู้ติดต่อของคุณเท่านั้นที่สามารถลบข้อความแบบย้อนกลับไม่ได้ (คุณสามารถทำเครื่องหมายเพื่อลบได้)"; +"Only your contact can irreversibly delete messages (you can mark them for deletion). (24 hours)" = "เฉพาะผู้ติดต่อของคุณเท่านั้นที่สามารถลบข้อความแบบย้อนกลับไม่ได้ (คุณสามารถทำเครื่องหมายเพื่อลบได้)"; /* No comment provided by engineer. */ "Only your contact can make calls." = "ผู้ติดต่อของคุณเท่านั้นที่สามารถโทรออกได้"; @@ -2225,9 +2201,6 @@ /* No comment provided by engineer. */ "Open-source protocol and code – anybody can run the servers." = "โปรโตคอลและโค้ดโอเพ่นซอร์ส – ใคร ๆ ก็สามารถเปิดใช้เซิร์ฟเวอร์ได้"; -/* No comment provided by engineer. */ -"Opening database…" = "กำลังเปิดฐานข้อมูล…"; - /* member role */ "owner" = "เจ้าของ"; @@ -2249,15 +2222,9 @@ /* No comment provided by engineer. */ "Password to show" = "รหัสผ่านที่จะแสดง"; -/* No comment provided by engineer. */ -"Paste" = "แปะ"; - /* No comment provided by engineer. */ "Paste image" = "แปะภาพ"; -/* No comment provided by engineer. */ -"Paste received link" = "แปะลิงก์ที่ได้รับ"; - /* No comment provided by engineer. */ "peer-to-peer" = "เพื่อนต่อเพื่อน"; @@ -2789,9 +2756,6 @@ /* No comment provided by engineer. */ "Share link" = "แชร์ลิงก์"; -/* No comment provided by engineer. */ -"Share one-time invitation link" = "แชร์ลิงก์เชิญแบบใช้ครั้งเดียว"; - /* No comment provided by engineer. */ "Share with contacts" = "แชร์กับผู้ติดต่อ"; @@ -2858,9 +2822,6 @@ /* notification title */ "Somebody" = "ใครบางคน"; -/* No comment provided by engineer. */ -"Start a new chat" = "เริ่มแชทใหม่"; - /* No comment provided by engineer. */ "Start chat" = "เริ่มแชท"; @@ -3020,12 +2981,6 @@ /* No comment provided by engineer. */ "Theme" = "ธีม"; -/* No comment provided by engineer. */ -"There should be at least one user profile." = "ควรมีโปรไฟล์ผู้ใช้อย่างน้อยหนึ่งโปรไฟล์"; - -/* No comment provided by engineer. */ -"There should be at least one visible user profile." = "ควรมีอย่างน้อยหนึ่งโปรไฟล์ผู้ใช้ที่มองเห็นได้"; - /* No comment provided by engineer. */ "These settings are for your current profile **%@**." = "การตั้งค่าเหล่านี้ใช้สำหรับโปรไฟล์ปัจจุบันของคุณ **%@**"; @@ -3089,9 +3044,6 @@ /* No comment provided by engineer. */ "Turn off" = "ปิด"; -/* No comment provided by engineer. */ -"Turn off notifications?" = "ปิดการแจ้งเตือนไหม?"; - /* No comment provided by engineer. */ "Turn on" = "เปิด"; @@ -3353,9 +3305,6 @@ /* No comment provided by engineer. */ "You can accept calls from lock screen, without device and app authentication." = "คุณสามารถรับสายจากหน้าจอล็อกโดยไม่ต้องมีการตรวจสอบสิทธิ์อุปกรณ์และแอป"; -/* No comment provided by engineer. */ -"You can also connect by clicking the link. If it opens in the browser, click **Open in mobile app** button." = "คุณสามารถเชื่อมต่อได้โดยคลิกที่ลิงค์ หากเปิดในเบราว์เซอร์ ให้คลิกปุ่ม **เปิดในแอปมือถือ**"; - /* No comment provided by engineer. */ "You can create it later" = "คุณสามารถสร้างได้ในภายหลัง"; @@ -3503,9 +3452,6 @@ /* No comment provided by engineer. */ "Your contacts can allow full message deletion." = "ผู้ติดต่อของคุณสามารถอนุญาตให้ลบข้อความทั้งหมดได้"; -/* No comment provided by engineer. */ -"Your contacts in SimpleX will see it.\nYou can change it in Settings." = "ผู้ติดต่อของคุณใน SimpleX จะเห็น\nคุณสามารถเปลี่ยนได้ในการตั้งค่า"; - /* No comment provided by engineer. */ "Your contacts will remain connected." = "ผู้ติดต่อของคุณจะยังคงเชื่อมต่ออยู่"; diff --git a/apps/ios/tr.lproj/Localizable.strings b/apps/ios/tr.lproj/Localizable.strings new file mode 100644 index 0000000000..75046c08f4 --- /dev/null +++ b/apps/ios/tr.lproj/Localizable.strings @@ -0,0 +1,4039 @@ +/* No comment provided by engineer. */ +"\n" = "\n"; + +/* No comment provided by engineer. */ +" " = " "; + +/* No comment provided by engineer. */ +" " = " "; + +/* No comment provided by engineer. */ +" " = " "; + +/* No comment provided by engineer. */ +" (" = " ("; + +/* No comment provided by engineer. */ +" (can be copied)" = " (kopyalanabilir)"; + +/* No comment provided by engineer. */ +"_italic_" = "\\_italik_"; + +/* No comment provided by engineer. */ +"- connect to [directory service](simplex:/contact#/?v=1-4&smp=smp%3A%2F%2Fu2dS9sG8nMNURyZwqASV4yROM28Er0luVTx5X1CsMrU%3D%40smp4.simplex.im%2FeXSPwqTkKyDO3px4fLf1wx3MvPdjdLW3%23%2F%3Fv%3D1-2%26dh%3DMCowBQYDK2VuAyEAaiv6MkMH44L2TcYrt_CsX3ZvM11WgbMEUn0hkIKTOho%253D%26srv%3Do5vmywmrnaxalvz6wi3zicyftgio6psuvyniis6gco6bp6ekl4cqj4id.onion) (BETA)!\n- delivery receipts (up to 20 members).\n- faster and more stable." = "- [dizin hizmeti] 'ne bağlan(simplex:/contact#/?v=1-4&smp=smp%3A%2F%2Fu2dS9sG8nMNURyZwqASV4yROM28Er0luVTx5X1CsMrU%3D%40smp4.simplex.im%2FeXSPwqTkKyDO3px4fLf1wx3MvPdjdLW3%23%2F%3Fv%3D1-2%26dh%3DMCowBQYDK2VuAyEAaiv6MkMH44L2TcYrt_CsX3ZvM11WgbMEUn0hkIKTOho%253D%26srv%3Do5vmywmrnaxalvz6wi3zicyftgio6psuvyniis6gco6bp6ekl4cqj4id.onion) (BETA)!\n- çoklu mesaj gönderimi (20 kişiye kadar).\n- daha hızlı ve daha stabil."; + +/* No comment provided by engineer. */ +"- more stable message delivery.\n- a bit better groups.\n- and more!" = "- daha stabil mesaj gönderimi.\n- birazcık daha iyi gruplar.\n- ve fazlası!"; + +/* No comment provided by engineer. */ +"- optionally notify deleted contacts.\n- profile names with spaces.\n- and more!" = "- isteğe bağlı olarak silinen kişilere bildirme.\n- boşluklu profil adları\n- ve fazlası!"; + +/* No comment provided by engineer. */ +"- voice messages up to 5 minutes.\n- custom time to disappear.\n- editing history." = "- 5 dakikaya kadar süren sesli mesajlar.\n- mesaj kaybolması için özel zaman.\n- düzenleme geçmişi."; + +/* No comment provided by engineer. */ +", " = ", "; + +/* No comment provided by engineer. */ +": " = ": "; + +/* No comment provided by engineer. */ +"!1 colored!" = "!1 renklendirilmiş!"; + +/* No comment provided by engineer. */ +"." = "."; + +/* No comment provided by engineer. */ +"(" = "("; + +/* No comment provided by engineer. */ +"(new)" = "(yeni)"; + +/* No comment provided by engineer. */ +"(this device v%@)" = "(bu cihaz v%@)"; + +/* No comment provided by engineer. */ +")" = ")"; + +/* No comment provided by engineer. */ +"[Contribute](https://github.com/simplex-chat/simplex-chat#contribute)" = "[Katkıda bulun](https://github.com/simplex-chat/simplex-chat#contribute)"; + +/* No comment provided by engineer. */ +"[Send us email](mailto:chat@simplex.chat)" = "[Bize e-posta gönder](mailto:chat@simplex.chat)"; + +/* No comment provided by engineer. */ +"[Star on GitHub](https://github.com/simplex-chat/simplex-chat)" = "[Bize GitHub'da yıldız verin](https://github.com/simplex-chat/simplex-chat)"; + +/* No comment provided by engineer. */ +"**Add contact**: to create a new invitation link, or connect via a link you received." = "**Kişi ekle**: yeni bir davet bağlantısı oluşturmak için, ya da aldığın bağlantıyla bağlan."; + +/* No comment provided by engineer. */ +"**Add new contact**: to create your one-time QR Code for your contact." = "**Yeni kişi ekleyin**: tek seferlik QR Kodunuzu oluşturmak veya kişisel ulaşım bilgileri bağlantısı için."; + +/* No comment provided by engineer. */ +"**Create group**: to create a new group." = "**Grup oluştur**: yeni bir grup oluşturmak için."; + +/* No comment provided by engineer. */ +"**e2e encrypted** audio call" = "**uçtan uca şifrelenmiş** sesli arama"; + +/* No comment provided by engineer. */ +"**e2e encrypted** video call" = "**uçtan uca şifrelenmiş** görüntülü arama"; + +/* No comment provided by engineer. */ +"**More private**: check new messages every 20 minutes. Device token is shared with SimpleX Chat server, but not how many contacts or messages you have." = "**Daha gizli**: her 20 dakikada yeni mesajlar için kontrol et. Cihaz jetonu SimpleX Chat sunucusuyla paylaşılacak, ama ne kadar kişi veya mesaja sahip olduğun paylaşılmayacak."; + +/* No comment provided by engineer. */ +"**Most private**: do not use SimpleX Chat notifications server, check messages periodically in the background (depends on how often you use the app)." = "**En gizli**: SimpleX Chat bildirim sunucusunu kullanma, arkaplanda mesajları periyodik olarak kontrol edin (uygulamayı ne sıklıkta kullandığınıza bağlıdır)."; + +/* No comment provided by engineer. */ +"**Please note**: you will NOT be able to recover or change passphrase if you lose it." = "**Lütfen aklınızda bulunsun**: eğer parolanızı kaybederseniz parolanızı değiştirme veya geri kurtarma ihtimaliniz YOKTUR."; + +/* No comment provided by engineer. */ +"**Recommended**: device token and notifications are sent to SimpleX Chat notification server, but not the message content, size or who it is from." = "**Önerilen**: cihaz tokeni ve bildirimler SimpleX Chat bildirim sunucularına gönderilir, ama mesajın içeriği, boyutu veya kimden geldiği gönderilmez."; + +/* No comment provided by engineer. */ +"**Warning**: Instant push notifications require passphrase saved in Keychain." = "**Dikkat**: Anında iletilen bildirimlere Anahtar Zinciri'nde kaydedilmiş parola gereklidir."; + +/* No comment provided by engineer. */ +"*bold*" = "\\*kalın*"; + +/* copied message info title, # <title> */ +"# %@" = "# %@"; + +/* copied message info */ +"## History" = "## Geçmiş"; + +/* copied message info */ +"## In reply to" = "## cevap olarak"; + +/* No comment provided by engineer. */ +"#secret#" = "#gizli#"; + +/* No comment provided by engineer. */ +"%@" = "%@"; + +/* No comment provided by engineer. */ +"%@ (current)" = "%@ (güncel)"; + +/* copied message info */ +"%@ (current):" = "%@ (güncel):"; + +/* No comment provided by engineer. */ +"%@ / %@" = "%@ / %@"; + +/* No comment provided by engineer. */ +"%@ %@" = "%@ %@"; + +/* No comment provided by engineer. */ +"%@ and %@" = "%@ ve %@"; + +/* No comment provided by engineer. */ +"%@ and %@ connected" = "%@ ve %@ bağlandı"; + +/* copied message info, <sender> at <time> */ +"%@ at %@:" = "%1$@, %2$@ de"; + +/* No comment provided by engineer. */ +"%@ connected" = "%@ bağlandı"; + +/* notification title */ +"%@ is connected!" = "%@ bağlandı!"; + +/* No comment provided by engineer. */ +"%@ is not verified" = "%@ onaylanmadı"; + +/* No comment provided by engineer. */ +"%@ is verified" = "%@ onaylandı"; + +/* No comment provided by engineer. */ +"%@ servers" = "%@ sunucuları"; + +/* notification title */ +"%@ wants to connect!" = "%@ bağlanmak istiyor!"; + +/* No comment provided by engineer. */ +"%@, %@ and %lld members" = "%@, %@ ve %lld üyeleri"; + +/* No comment provided by engineer. */ +"%@, %@ and %lld other members connected" = "%@, %@ ve %lld diğer üyeler bağlandı"; + +/* copied message info */ +"%@:" = "%@:"; + +/* time interval */ +"%d days" = "%d gün"; + +/* time interval */ +"%d hours" = "%d saat"; + +/* time interval */ +"%d min" = "%d dakika"; + +/* time interval */ +"%d months" = "%d ay"; + +/* time interval */ +"%d sec" = "%d saniye"; + +/* integrity error chat item */ +"%d skipped message(s)" = "%d okunmamış mesaj(lar)"; + +/* time interval */ +"%d weeks" = "%d hafta"; + +/* No comment provided by engineer. */ +"%lld" = "%lld"; + +/* No comment provided by engineer. */ +"%lld %@" = "%lld %@"; + +/* No comment provided by engineer. */ +"%lld contact(s) selected" = "%lld kişi seçildi"; + +/* No comment provided by engineer. */ +"%lld file(s) with total size of %@" = "%lld dosya , toplam büyüklüğü %@"; + +/* No comment provided by engineer. */ +"%lld group events" = "%lld grup etkinlikleri"; + +/* No comment provided by engineer. */ +"%lld members" = "%lld üyeler"; + +/* No comment provided by engineer. */ +"%lld messages blocked" = "%lld mesajlar engellendi"; + +/* No comment provided by engineer. */ +"%lld messages marked deleted" = "%lld mesajlar silinmiş olarak işaretlendi"; + +/* No comment provided by engineer. */ +"%lld messages moderated by %@" = "%lld mesajları %@ tarafından yönetildi"; + +/* No comment provided by engineer. */ +"%lld minutes" = "%lld dakika"; + +/* No comment provided by engineer. */ +"%lld new interface languages" = "%lld yeni arayüz dilleri"; + +/* No comment provided by engineer. */ +"%lld second(s)" = "%lld saniye"; + +/* No comment provided by engineer. */ +"%lld seconds" = "%lld saniye"; + +/* No comment provided by engineer. */ +"%lldd" = "%lldd"; + +/* No comment provided by engineer. */ +"%lldh" = "%lldh"; + +/* No comment provided by engineer. */ +"%lldk" = "%lldk"; + +/* No comment provided by engineer. */ +"%lldm" = "%lldm"; + +/* No comment provided by engineer. */ +"%lldmth" = "%lldmth"; + +/* No comment provided by engineer. */ +"%llds" = "%llds"; + +/* No comment provided by engineer. */ +"%lldw" = "%lldw"; + +/* No comment provided by engineer. */ +"%u messages failed to decrypt." = "%u mesajın şifreleme çözümü başarısız oldu."; + +/* No comment provided by engineer. */ +"%u messages skipped." = "%u mesaj atlandı"; + +/* No comment provided by engineer. */ +"`a + b`" = "\\`a + b`"; + +/* email text */ +"<p>Hi!</p>\n<p><a href=\"%@\">Connect to me via SimpleX Chat</a></p>" = "<p>Merhaba!</p>\n<p><a href=\"%@\">SimpleX Chat ile bana bağlanın</a></p>"; + +/* No comment provided by engineer. */ +"~strike~" = "\\~strike~"; + +/* time to disappear */ +"0 sec" = "0 saniye"; + +/* No comment provided by engineer. */ +"0s" = "0 saniye"; + +/* time interval */ +"1 day" = "1 gün"; + +/* time interval */ +"1 hour" = "1 saat"; + +/* No comment provided by engineer. */ +"1 minute" = "1 dakika"; + +/* time interval */ +"1 month" = "1 ay"; + +/* time interval */ +"1 week" = "1 hafta"; + +/* No comment provided by engineer. */ +"5 minutes" = "5 dakika"; + +/* No comment provided by engineer. */ +"6" = "6"; + +/* No comment provided by engineer. */ +"30 seconds" = "30 saniye"; + +/* No comment provided by engineer. */ +"A few more things" = "Birkaç şey daha"; + +/* notification title */ +"A new contact" = "Yeni kişi"; + +/* No comment provided by engineer. */ +"A new random profile will be shared." = "Yeni bir rastgele profil paylaşılacak."; + +/* No comment provided by engineer. */ +"A separate TCP connection will be used **for each chat profile you have in the app**." = "**uygulamandaki olan her sohbet profili için** ayrı bir TCP bağlantısı kullanılacaktır."; + +/* No comment provided by engineer. */ +"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." = "**uygulamandaki olan her sohbet profili için** ayrı bir TCP bağlantısı kullanılacaktır.\n**Lütfen aklınızda bulunsun**: eğer çok fazla bağlantılarınız var ise pil kullanımı ve internet kullanımınız oldukça artabilir ve bazı bağlantılar hatayla karşılaşabilir."; + +/* No comment provided by engineer. */ +"Abort" = "İptal Et"; + +/* No comment provided by engineer. */ +"Abort changing address" = "Adres değişimini iptal et"; + +/* No comment provided by engineer. */ +"Abort changing address?" = "Adres değişimi iptal edilsin mi?"; + +/* No comment provided by engineer. */ +"About SimpleX" = "SimpleX Hakkında"; + +/* No comment provided by engineer. */ +"About SimpleX address" = "SimpleX Chat adresi hakkında"; + +/* No comment provided by engineer. */ +"About SimpleX Chat" = "SimpleX Chat hakkında"; + +/* No comment provided by engineer. */ +"above, then choose:" = "yukarı çıkın, ardından seçin:"; + +/* No comment provided by engineer. */ +"Accent color" = "Vurgu rengi"; + +/* accept contact request via notification + accept incoming call via notification */ +"Accept" = "Kabul et"; + +/* No comment provided by engineer. */ +"Accept connection request?" = "Bağlantı isteği kabul edilsin mi?"; + +/* notification body */ +"Accept contact request from %@?" = "%@ 'den gelen iletişim isteği kabul edilsin mi?"; + +/* accept contact request via notification */ +"Accept incognito" = "Takma adla kabul et"; + +/* call status */ +"accepted call" = "kabul edilen arama"; + +/* No comment provided by engineer. */ +"Add address to your profile, so that your contacts can share it with other people. Profile update will be sent to your contacts." = "Kişilerinizin başkalarıyla paylaşabilmesi için profilinize adres ekleyin. Profil güncellemesi kişilerinize gönderilecek."; + +/* No comment provided by engineer. */ +"Add contact" = "Kişi ekle"; + +/* No comment provided by engineer. */ +"Add preset servers" = "Önceden ayarlanmış sunucu ekle"; + +/* No comment provided by engineer. */ +"Add profile" = "Profil ekle"; + +/* No comment provided by engineer. */ +"Add server…" = "Sunucu ekle…"; + +/* No comment provided by engineer. */ +"Add servers by scanning QR codes." = "Karekod taratarak sunucuları ekleyin."; + +/* No comment provided by engineer. */ +"Add to another device" = "Başka bir cihaza ekle"; + +/* No comment provided by engineer. */ +"Add welcome message" = "Karşılama mesajı ekleyin"; + +/* No comment provided by engineer. */ +"Address" = "Adres"; + +/* No comment provided by engineer. */ +"Address change will be aborted. Old receiving address will be used." = "Adres değişikliği iptal edilecek. Eski alıcı adresi kullanılacaktır."; + +/* member role */ +"admin" = "yönetici"; + +/* No comment provided by engineer. */ +"Admins can create the links to join groups." = "Yöneticiler gruplara katılmak için bağlantılar oluşturabilir."; + +/* No comment provided by engineer. */ +"Advanced network settings" = "GGelişmiş ağ ayarları"; + +/* chat item text */ +"agreeing encryption for %@…" = "%@ için şifreleme kabul ediliyor…"; + +/* chat item text */ +"agreeing encryption…" = "şifreleme kabul ediliyor…"; + +/* No comment provided by engineer. */ +"All app data is deleted." = "Tüm uygulama verileri silinir."; + +/* No comment provided by engineer. */ +"All chats and messages will be deleted - this cannot be undone!" = "Tüm konuşmalar ve mesajlar silinecektir. Bu, geri alınamaz!"; + +/* No comment provided by engineer. */ +"All data is erased when it is entered." = "Kullanıldığında bütün veriler silinir."; + +/* No comment provided by engineer. */ +"All group members will remain connected." = "Tüm grup üyeleri bağlı kalacaktır."; + +/* No comment provided by engineer. */ +"All messages will be deleted - this cannot be undone! The messages will be deleted ONLY for you." = "Tüm mesajlar silinecektir. Bu, geri alınamaz! Mesajlar, YALNIZCA senin için silinecektir."; + +/* No comment provided by engineer. */ +"All new messages from %@ will be hidden!" = "%@ 'den gelen bütün yeni mesajlar saklı olacak!"; + +/* No comment provided by engineer. */ +"All your contacts will remain connected." = "Konuştuğun kişilerin tümü bağlı kalacaktır."; + +/* No comment provided by engineer. */ +"All your contacts will remain connected. Profile update will be sent to your contacts." = "Tüm kişileriniz bağlı kalacaktır. Profil güncellemesi kişilerinize gönderilecektir."; + +/* No comment provided by engineer. */ +"Allow" = "İzin ver"; + +/* No comment provided by engineer. */ +"Allow calls only if your contact allows them." = "Yalnızca irtibat kişiniz izin veriyorsa aramalara izin verin."; + +/* No comment provided by engineer. */ +"Allow disappearing messages only if your contact allows it to you." = "Eğer kişide izin verirse kaybolan mesajlara izin ver."; + +/* No comment provided by engineer. */ +"Allow message reactions only if your contact allows them." = "Yalnızca kişin mesaj tepkilerine izin veriyorsa sen de ver."; + +/* No comment provided by engineer. */ +"Allow message reactions." = "Mesaj tepkilerine izin ver."; + +/* No comment provided by engineer. */ +"Allow sending direct messages to members." = "Üyelere direkt mesaj göndermeye izin ver."; + +/* No comment provided by engineer. */ +"Allow sending disappearing messages." = "Kendiliğinden yok olan mesajlar göndermeye izin ver."; + +/* No comment provided by engineer. */ +"Allow to send files and media." = "Dosya ve medya göndermeye izin ver."; + +/* No comment provided by engineer. */ +"Allow to send voice messages." = "Sesli mesaj göndermeye izin ver."; + +/* No comment provided by engineer. */ +"Allow voice messages only if your contact allows them." = "Yalnızca kişiniz sesli mesaj göndermeye izin veriyorsa sen de ver."; + +/* No comment provided by engineer. */ +"Allow voice messages?" = "Sesli mesajlara izin ver?"; + +/* No comment provided by engineer. */ +"Allow your contacts adding message reactions." = "Konuştuğun kişilerin mesajlarına tepki eklemesine izin ver."; + +/* No comment provided by engineer. */ +"Allow your contacts to call you." = "Kişilerinin seni aramasına izin ver."; + +/* No comment provided by engineer. */ +"Allow your contacts to send disappearing messages." = "Kişilerinizin kaybolan mesajlar göndermesine izin verin."; + +/* No comment provided by engineer. */ +"Allow your contacts to send voice messages." = "Kişilerinizin sesli mesajlar göndermesine izin verin."; + +/* No comment provided by engineer. */ +"Already connected?" = "Zaten bağlandı?"; + +/* No comment provided by engineer. */ +"Already connecting!" = "Zaten bağlanılıyor!"; + +/* No comment provided by engineer. */ +"Already joining the group!" = "Zaten gruba bağlanılıyor!"; + +/* pref value */ +"always" = "her zaman"; + +/* No comment provided by engineer. */ +"Always use relay" = "Her zaman yönlendirici kulan"; + +/* No comment provided by engineer. */ +"An empty chat profile with the provided name is created, and the app opens as usual." = "Verilen adla boş bir sohbet profili oluşturulur ve uygulama her zamanki gibi açılır."; + +/* No comment provided by engineer. */ +"and %lld other events" = "ve %lld diğer etkinlikler"; + +/* No comment provided by engineer. */ +"Answer call" = "Aramayı cevapla"; + +/* No comment provided by engineer. */ +"App build: %@" = "Uygulama sürümü: %@"; + +/* No comment provided by engineer. */ +"App encrypts new local files (except videos)." = "Uygulama yerel dosyaları şifreler (videolar dışında)."; + +/* No comment provided by engineer. */ +"App icon" = "Uygulama simgesi"; + +/* No comment provided by engineer. */ +"App passcode" = "Uygulama erişim kodu"; + +/* No comment provided by engineer. */ +"App passcode is replaced with self-destruct passcode." = "Uygulama parolası kendi kendini imha eden parolayla değiştirildi."; + +/* No comment provided by engineer. */ +"App version" = "Uygulama sürümü"; + +/* No comment provided by engineer. */ +"App version: v%@" = "Uygulama sürümü: v%@"; + +/* No comment provided by engineer. */ +"Appearance" = "Görünüş"; + +/* No comment provided by engineer. */ +"Attach" = "Ekle"; + +/* No comment provided by engineer. */ +"Audio & video calls" = "Sesli & görüntülü aramalar"; + +/* No comment provided by engineer. */ +"Audio and video calls" = "Sesli ve görüntülü aramalar"; + +/* No comment provided by engineer. */ +"audio call (not e2e encrypted)" = "sesli arama (uçtan uca şifreli değil)"; + +/* chat feature */ +"Audio/video calls" = "Sesli/görüntülü aramalar"; + +/* No comment provided by engineer. */ +"Audio/video calls are prohibited." = "Sesli/görüntülü aramalar yasaklandı."; + +/* PIN entry */ +"Authentication cancelled" = "Kimlik doğrulama iptal edildi"; + +/* No comment provided by engineer. */ +"Authentication failed" = "Kimlik doğrulama başarısız oldu"; + +/* No comment provided by engineer. */ +"Authentication is required before the call is connected, but you may miss calls." = "Kimlik doğrulama aramalara bağlanmadan önce gereklidir, ama aramaları kaçırabilirsin."; + +/* No comment provided by engineer. */ +"Authentication unavailable" = "Kimlik doğrulama kullanım dışı"; + +/* member role */ +"author" = "yetkili"; + +/* No comment provided by engineer. */ +"Auto-accept" = "Otomatik-kabul et"; + +/* No comment provided by engineer. */ +"Auto-accept contact requests" = "İletişim isteklerini otomatik kabul et"; + +/* No comment provided by engineer. */ +"Auto-accept images" = "Fotoğrafları otomatik kabul et"; + +/* No comment provided by engineer. */ +"Back" = "Geri"; + +/* No comment provided by engineer. */ +"Bad desktop address" = "Kötü bilgisayar adresi"; + +/* integrity error chat item */ +"bad message hash" = "kötü mesaj hash'i"; + +/* No comment provided by engineer. */ +"Bad message hash" = "Kötü mesaj karması"; + +/* integrity error chat item */ +"bad message ID" = "kötü mesaj kimliği"; + +/* No comment provided by engineer. */ +"Bad message ID" = "Kötü mesaj kimliği"; + +/* No comment provided by engineer. */ +"Better groups" = "Daha iyi gruplar"; + +/* No comment provided by engineer. */ +"Better messages" = "Daha iyi mesajlar"; + +/* No comment provided by engineer. */ +"Block" = "Engelle"; + +/* No comment provided by engineer. */ +"Block group members" = "Grup üyelerini engelle"; + +/* No comment provided by engineer. */ +"Block member" = "Üyeyi engelle"; + +/* No comment provided by engineer. */ +"Block member?" = "Üyeyi engelle?"; + +/* No comment provided by engineer. */ +"blocked" = "engellendi"; + +/* No comment provided by engineer. */ +"bold" = "kalın"; + +/* No comment provided by engineer. */ +"Both you and your contact can add message reactions." = "Sen ve konuştuğun kişi mesaj tepkileri ekleyebilir."; + +/* No comment provided by engineer. */ +"Both you and your contact can make calls." = "Sen ve konuştuğun kişi aramalar yapabilir."; + +/* No comment provided by engineer. */ +"Both you and your contact can send disappearing messages." = "Sen ve konuştuğun kişi kaybolan mesajlar gönderebilir."; + +/* No comment provided by engineer. */ +"Both you and your contact can send voice messages." = "Sen ve konuştuğun kişi sesli mesaj gönderebilir."; + +/* No comment provided by engineer. */ +"Bulgarian, Finnish, Thai and Ukrainian - thanks to the users and [Weblate](https://github.com/simplex-chat/simplex-chat/tree/stable#help-translating-simplex-chat)!" = "Bulgarca, Fince, Tayca ve Ukraynaca - kullanıcılara ve [Weblate] e teşekkürler! (https://github.com/simplex-chat/simplex-chat/tree/stable#help-translating-simplex-chat)!"; + +/* No comment provided by engineer. */ +"By chat profile (default) or [by connection](https://simplex.chat/blog/20230204-simplex-chat-v4-5-user-chat-profiles.html#transport-isolation) (BETA)." = "Sohbet profiline göre (varsayılan) veya [bağlantıya göre](https://simplex.chat/blog/20230204-simplex-chat-v4-5-user-chat-profiles.html#transport-isolation) (BETA)."; + +/* No comment provided by engineer. */ +"Call already ended!" = "Arama çoktan bitti!"; + +/* call status */ +"call error" = "arama hatası"; + +/* call status */ +"call in progress" = "arama yapılıyor"; + +/* call status */ +"calling…" = "aranıyor…"; + +/* No comment provided by engineer. */ +"Calls" = "Aramalar"; + +/* No comment provided by engineer. */ +"Camera not available" = "Kamera mevcut değil"; + +/* No comment provided by engineer. */ +"Can't invite contact!" = "Kişi davet edilemiyor!"; + +/* No comment provided by engineer. */ +"Can't invite contacts!" = "Kişiler davet edilemiyor!"; + +/* No comment provided by engineer. */ +"Cancel" = "İptal et"; + +/* feature offered item */ +"cancelled %@" = "%@ iptal edildi"; + +/* 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 receive file" = "Dosya alınamıyor"; + +/* No comment provided by engineer. */ +"Change" = "Değiştir"; + +/* No comment provided by engineer. */ +"Change database passphrase?" = "Veritabanı parolasını değiştir?"; + +/* authentication reason */ +"Change lock mode" = "Kilit modunu değiştir"; + +/* No comment provided by engineer. */ +"Change member role?" = "Üye rolünü değiştir?"; + +/* authentication reason */ +"Change passcode" = "Şifreyi değiştir"; + +/* No comment provided by engineer. */ +"Change receiving address" = "Alıcı adresini değiştir"; + +/* No comment provided by engineer. */ +"Change receiving address?" = "Alıcı adresi değiştirilsin mi?"; + +/* No comment provided by engineer. */ +"Change role" = "Rolü değiştir"; + +/* authentication reason */ +"Change self-destruct mode" = "Kendini yok etme modunu değiştir"; + +/* authentication reason + set passcode view */ +"Change self-destruct passcode" = "Kendini yok eden parolayı değiştir"; + +/* chat item text */ +"changed address for you" = "senin için adres değiştirildi"; + +/* rcv group event chat item */ +"changed role of %@ to %@" = "1$@ rolünü %2$@ olarak değiştirdi"; + +/* rcv group event chat item */ +"changed your role to %@" = "rolünü %@ olarak değiştirdi"; + +/* chat item text */ +"changing address for %@…" = "%@ için adres değiştiriliyor…"; + +/* chat item text */ +"changing address…" = "adres değiştiriliyor…"; + +/* No comment provided by engineer. */ +"Chat archive" = "Sohbet arşivi"; + +/* No comment provided by engineer. */ +"Chat console" = "Sohbet konsolu"; + +/* No comment provided by engineer. */ +"Chat database" = "Sohbet veritabanı"; + +/* No comment provided by engineer. */ +"Chat database deleted" = "Sohbet veritabanı silindi"; + +/* No comment provided by engineer. */ +"Chat database imported" = "Sohbet veritabanı içe aktarıldı"; + +/* No comment provided by engineer. */ +"Chat is running" = "Sohbet çalışıyor"; + +/* No comment provided by engineer. */ +"Chat is stopped" = "Sohbet durdu"; + +/* No comment provided by engineer. */ +"Chat is stopped. If you already used this database on another device, you should transfer it back before starting chat." = "Sohbet durduruldu. Bu veritabanını zaten başka bir cihazda kullandıysanız, sohbete başlamadan önce onu geri aktarmalısınız."; + +/* No comment provided by engineer. */ +"Chat preferences" = "Sohbet tercihleri"; + +/* No comment provided by engineer. */ +"Chats" = "Sohbetler"; + +/* No comment provided by engineer. */ +"Check server address and try again." = "Sunucu adresini kontrol edip tekrar deneyin."; + +/* No comment provided by engineer. */ +"Chinese and Spanish interface" = "Çince ve İspanyolca arayüz"; + +/* No comment provided by engineer. */ +"Choose file" = "Dosya seç"; + +/* No comment provided by engineer. */ +"Choose from library" = "Kütüphaneden seç"; + +/* No comment provided by engineer. */ +"Clear" = "Temizle"; + +/* No comment provided by engineer. */ +"Clear conversation" = "Sohbeti temizle"; + +/* No comment provided by engineer. */ +"Clear conversation?" = "Sohbet temizlensin mi?"; + +/* No comment provided by engineer. */ +"Clear verification" = "Doğrulamayı temizle"; + +/* No comment provided by engineer. */ +"colored" = "renklendirilmiş"; + +/* No comment provided by engineer. */ +"Colors" = "Renkler"; + +/* server test step */ +"Compare file" = "Dosya karşılaştır"; + +/* No comment provided by engineer. */ +"Compare security codes with your contacts." = "Güvenlik kodlarını kişilerinle karşılaştır."; + +/* No comment provided by engineer. */ +"complete" = "tamamlandı"; + +/* No comment provided by engineer. */ +"Configure ICE servers" = "ICE sunucularını ayarla"; + +/* No comment provided by engineer. */ +"Confirm" = "Onayla"; + +/* No comment provided by engineer. */ +"Confirm database upgrades" = "Veritabanı geliştirmelerini onayla"; + +/* No comment provided by engineer. */ +"Confirm new passphrase…" = "Yeni parolayı onayla…"; + +/* No comment provided by engineer. */ +"Confirm Passcode" = "Parolayı onayla"; + +/* No comment provided by engineer. */ +"Confirm password" = "Şifreyi onayla"; + +/* server test step */ +"Connect" = "Bağlan"; + +/* No comment provided by engineer. */ +"Connect automatically" = "Otomatik olarak bağlan"; + +/* No comment provided by engineer. */ +"Connect incognito" = "Gizli bağlan"; + +/* No comment provided by engineer. */ +"Connect to desktop" = "Bilgisayara bağlan"; + +/* No comment provided by engineer. */ +"connect to SimpleX Chat developers." = "SimpleX Chat geliştiricilerine bağlan."; + +/* No comment provided by engineer. */ +"Connect to yourself?" = "Kendine mi bağlanacaksın?"; + +/* No comment provided by engineer. */ +"Connect to yourself?\nThis is your own one-time link!" = "Kendine mi bağlanacaksın?\nBu senin kendi tek kullanımlık bağlantın!"; + +/* No comment provided by engineer. */ +"Connect to yourself?\nThis is your own SimpleX address!" = "Kendine mi bağlanacaksın?\nBu senin kendi SimpleX adresin!"; + +/* No comment provided by engineer. */ +"Connect via contact address" = "Kişi adresi aracılığıyla bağlan"; + +/* No comment provided by engineer. */ +"Connect via link" = "Bağlantı aracılığıyla bağlan"; + +/* No comment provided by engineer. */ +"Connect via one-time link" = "Tek kullanımlık bağlantı aracılığıyla bağlan"; + +/* No comment provided by engineer. */ +"Connect with %@" = "%@ ile bağlan"; + +/* No comment provided by engineer. */ +"connected" = "bağlanıldı"; + +/* No comment provided by engineer. */ +"Connected desktop" = "Bilgisayara bağlandı"; + +/* rcv group event chat item */ +"connected directly" = "doğrudan bağlandı"; + +/* No comment provided by engineer. */ +"Connected to desktop" = "Bilgisayara bağlanıldı"; + +/* No comment provided by engineer. */ +"connecting" = "bağlanılıyor"; + +/* No comment provided by engineer. */ +"connecting (accepted)" = "bağlanılıyor (onaylandı)"; + +/* No comment provided by engineer. */ +"connecting (announced)" = "bağlanılıyor (duyuruldu)"; + +/* No comment provided by engineer. */ +"connecting (introduced)" = "bağlanılıyor (tanıtıldı)"; + +/* No comment provided by engineer. */ +"connecting (introduction invitation)" = "bağlanılıyor (tanıtılma isteği)"; + +/* call status */ +"connecting call" = "aramaya bağlanılıyor…"; + +/* No comment provided by engineer. */ +"Connecting server…" = "Sunucuya bağlanıyor…"; + +/* No comment provided by engineer. */ +"Connecting server… (error: %@)" = "Sunucuya bağlanıyor…(hata:%@)"; + +/* No comment provided by engineer. */ +"Connecting to desktop" = "Bilgisayara bağlanıyor"; + +/* chat list item title */ +"connecting…" = "bağlanılıyor…"; + +/* No comment provided by engineer. */ +"Connection" = "Bağlantı"; + +/* No comment provided by engineer. */ +"Connection error" = "Bağlantı hatası"; + +/* No comment provided by engineer. */ +"Connection error (AUTH)" = "Bağlantı hatası (DOĞRULAMA)"; + +/* chat list item title (it should not be shown */ +"connection established" = "bağlantı kuruldu"; + +/* No comment provided by engineer. */ +"Connection request sent!" = "Bağlantı daveti gönderildi!"; + +/* No comment provided by engineer. */ +"Connection terminated" = "Bağlantı sonlandırılmış"; + +/* No comment provided by engineer. */ +"Connection timeout" = "Bağlantı süresi geçmiş"; + +/* connection information */ +"connection:%@" = "bağlantı:%@"; + +/* No comment provided by engineer. */ +"Contact allows" = "Kişi izin veriyor"; + +/* No comment provided by engineer. */ +"Contact already exists" = "Kişi zaten mevcut"; + +/* No comment provided by engineer. */ +"contact has e2e encryption" = "kişi uçtan uca şifrelemeye sahiptir"; + +/* No comment provided by engineer. */ +"contact has no e2e encryption" = "kişi uçtan uca şifrelemeye sahip değildir"; + +/* notification */ +"Contact hidden:" = "Kişi gizli:"; + +/* notification */ +"Contact is connected" = "Kişi bağlandı"; + +/* No comment provided by engineer. */ +"Contact is not connected yet!" = "Kişi şuan bağlanmadı!"; + +/* No comment provided by engineer. */ +"Contact name" = "Kişi adı"; + +/* No comment provided by engineer. */ +"Contact preferences" = "Kişi tercihleri"; + +/* No comment provided by engineer. */ +"Contacts" = "Kişiler"; + +/* No comment provided by engineer. */ +"Contacts can mark messages for deletion; you will be able to view them." = "Kişiler silinmesi için mesajları işaretleyebilir; onları görüntüleyebilirsin."; + +/* No comment provided by engineer. */ +"Continue" = "Devam et"; + +/* chat item action */ +"Copy" = "Kopyala"; + +/* No comment provided by engineer. */ +"Core version: v%@" = "Çekirdek sürümü: v%@"; + +/* No comment provided by engineer. */ +"Correct name to %@?" = "İsim %@ olarak düzeltilsin mi?"; + +/* No comment provided by engineer. */ +"Create" = "Oluştur"; + +/* No comment provided by engineer. */ +"Create a group using a random profile." = "Rasgele profil kullanarak grup oluştur."; + +/* No comment provided by engineer. */ +"Create an address to let people connect with you." = "İnsanların seninle bağlanması için bir adres oluştur."; + +/* server test step */ +"Create file" = "Dosya oluştur"; + +/* No comment provided by engineer. */ +"Create group" = "Grup oluştur"; + +/* No comment provided by engineer. */ +"Create group link" = "Grup bağlantısı oluştur"; + +/* No comment provided by engineer. */ +"Create link" = "Bağlantı oluştur"; + +/* No comment provided by engineer. */ +"Create new profile in [desktop app](https://simplex.chat/downloads/). 💻" = "[bilgisayar uygulaması] nda yeni bir profil oluştur(https://simplex.chat/downloads/). 💻"; + +/* No comment provided by engineer. */ +"Create profile" = "Profil oluştur"; + +/* server test step */ +"Create queue" = "Sıra oluştur"; + +/* No comment provided by engineer. */ +"Create secret group" = "Gizli grup oluştur"; + +/* No comment provided by engineer. */ +"Create SimpleX address" = "SimpleX adresi oluştur"; + +/* No comment provided by engineer. */ +"Create your profile" = "Profilini oluştur"; + +/* No comment provided by engineer. */ +"Created on %@" = "%@ de oluşturuldu"; + +/* No comment provided by engineer. */ +"Creating link…" = "Link oluşturuluyor…"; + +/* No comment provided by engineer. */ +"creator" = "oluşturan"; + +/* No comment provided by engineer. */ +"Current Passcode" = "Şu anki şifre"; + +/* No comment provided by engineer. */ +"Current passphrase…" = "Şu anki parola…"; + +/* No comment provided by engineer. */ +"Currently maximum supported file size is %@." = "Şu anki maksimum desteklenen dosya boyutu %@ kadardır."; + +/* dropdown time picker choice */ +"custom" = "özel"; + +/* No comment provided by engineer. */ +"Custom time" = "Özel saat"; + +/* No comment provided by engineer. */ +"Dark" = "Karanlık"; + +/* No comment provided by engineer. */ +"Database downgrade" = "Veritabanı sürüm düşürme"; + +/* No comment provided by engineer. */ +"Database encrypted!" = "Veritabanı şifrelendi!"; + +/* No comment provided by engineer. */ +"Database encryption passphrase will be updated and stored in the keychain.\n" = "Veritabanı şifreleme parolası güncellenecek ve Anahtar Zinciri'nde saklanacaktır.\n"; + +/* No comment provided by engineer. */ +"Database encryption passphrase will be updated.\n" = "Veritabanı şifreleme parolası güncellenecektir.\n"; + +/* No comment provided by engineer. */ +"Database error" = "Veritabanı hatası"; + +/* No comment provided by engineer. */ +"Database ID" = "Veritabanı kimliği"; + +/* copied message info */ +"Database ID: %d" = "Veritabanı kimliği: %d"; + +/* No comment provided by engineer. */ +"Database IDs and Transport isolation option." = "Veritabanı kimlikleri ve Taşıma izolasyonu seçeneği."; + +/* No comment provided by engineer. */ +"Database is encrypted using a random passphrase, you can change it." = "Veritabanı rastgele bir parola kullanılarak şifrelenir, bunu değiştirebilirsiniz."; + +/* No comment provided by engineer. */ +"Database is encrypted using a random passphrase. Please change it before exporting." = "Veritabanı rastgele bir parola kullanılarak şifrelenir. Lütfen dışa aktarmadan önce değiştirin."; + +/* No comment provided by engineer. */ +"Database passphrase" = "Veritabanı parolası"; + +/* No comment provided by engineer. */ +"Database passphrase & export" = "Veritabanı parolası ve dışa aktarma"; + +/* 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." = "Sohbeti açmak için veritabanı parolası gereklidir."; + +/* No comment provided by engineer. */ +"Database upgrade" = "Veritabanı yükseltmesi"; + +/* No comment provided by engineer. */ +"database version is newer than the app, but no down migration for: %@" = "veritabanı sürümü uygulamadan daha yeni, ancak aşağı geçiş yok: %@"; + +/* No comment provided by engineer. */ +"Database will be encrypted and the passphrase stored in the keychain.\n" = "Veritabanı şifrelenecek ve parola Anahtar Zinciri'nde saklanacaktır.\n"; + +/* No comment provided by engineer. */ +"Database will be encrypted.\n" = "Veritabanı şifrelenecektir.\n"; + +/* No comment provided by engineer. */ +"Database will be migrated when the app restarts" = "Uygulama yeniden başlatıldığında veritabanı taşınacaktır"; + +/* time unit */ +"days" = "gün"; + +/* No comment provided by engineer. */ +"Decentralized" = "Merkezi Olmayan"; + +/* message decrypt error item */ +"Decryption error" = "Şifre çözme hatası"; + +/* pref value */ +"default (%@)" = "varsayılan (%@)"; + +/* No comment provided by engineer. */ +"default (no)" = "varsayılan (hayır)"; + +/* No comment provided by engineer. */ +"default (yes)" = "varsayılan (evet)"; + +/* chat item action */ +"Delete" = "Sil"; + +/* No comment provided by engineer. */ +"Delete %lld messages?" = "%lld mesajları silinsin mi?"; + +/* No comment provided by engineer. */ +"Delete address" = "Adresi sil"; + +/* No comment provided by engineer. */ +"Delete address?" = "Adres silinsin mi?"; + +/* No comment provided by engineer. */ +"Delete after" = "Sonra sil"; + +/* No comment provided by engineer. */ +"Delete all files" = "Bütün dosyaları sil"; + +/* No comment provided by engineer. */ +"Delete and notify contact" = "Sil ve kişiye bildir"; + +/* No comment provided by engineer. */ +"Delete archive" = "Arşivi sil"; + +/* No comment provided by engineer. */ +"Delete chat archive?" = "Sohbet arşivi silinsin mi?"; + +/* No comment provided by engineer. */ +"Delete chat profile" = "Sohbet profilini sil"; + +/* No comment provided by engineer. */ +"Delete chat profile?" = "Sohbet profili silinsin mi?"; + +/* No comment provided by engineer. */ +"Delete connection" = "Bağlantıyı sil"; + +/* No comment provided by engineer. */ +"Delete contact" = "Kişiyi sil"; + +/* No comment provided by engineer. */ +"Delete Contact" = "Kişiyi sil"; + +/* No comment provided by engineer. */ +"Delete contact?\nThis cannot be undone!" = "Kişi silinsin mi?\nBu geri alınamaz!"; + +/* No comment provided by engineer. */ +"Delete database" = "Veritabanını sil"; + +/* server test step */ +"Delete file" = "Dosyayı sil"; + +/* No comment provided by engineer. */ +"Delete files and media?" = "Dosyalar ve medya silinsin mi?"; + +/* No comment provided by engineer. */ +"Delete files for all chat profiles" = "Bütün sohbet profilleri için dosyaları sil"; + +/* chat feature */ +"Delete for everyone" = "Herkesten sil"; + +/* No comment provided by engineer. */ +"Delete for me" = "Benden sil"; + +/* No comment provided by engineer. */ +"Delete group" = "Grubu sil"; + +/* No comment provided by engineer. */ +"Delete group?" = "Grup silinsin mi?"; + +/* No comment provided by engineer. */ +"Delete invitation" = "Daveti sil"; + +/* No comment provided by engineer. */ +"Delete link" = "Bağlantıyı sil"; + +/* No comment provided by engineer. */ +"Delete link?" = "Bağlantı silinsin mi?"; + +/* No comment provided by engineer. */ +"Delete member message?" = "Kişinin mesajı silinsin mi?"; + +/* No comment provided by engineer. */ +"Delete message?" = "Mesaj silinsin mi?"; + +/* No comment provided by engineer. */ +"Delete messages" = "Mesajları sil"; + +/* No comment provided by engineer. */ +"Delete messages after" = "Mesajları sonra sil"; + +/* No comment provided by engineer. */ +"Delete old database" = "Eski veritabanını sil"; + +/* No comment provided by engineer. */ +"Delete old database?" = "Eski veritabanı silinsin mi?"; + +/* No comment provided by engineer. */ +"Delete pending connection" = "Bekleyen bağlantıyı sil"; + +/* No comment provided by engineer. */ +"Delete pending connection?" = "Bekleyen bağlantı silinsin mi?"; + +/* No comment provided by engineer. */ +"Delete profile" = "Profili sil"; + +/* server test step */ +"Delete queue" = "Sırayı sil"; + +/* No comment provided by engineer. */ +"Delete user profile?" = "Kullanıcı profili silinsin mi?"; + +/* deleted chat item */ +"deleted" = "silindi"; + +/* No comment provided by engineer. */ +"Deleted at" = "de silindi"; + +/* copied message info */ +"Deleted at: %@" = "%@ de silindi"; + +/* rcv direct event chat item */ +"deleted contact" = "silinmiş kişi"; + +/* rcv group event chat item */ +"deleted group" = "silinmiş grup"; + +/* No comment provided by engineer. */ +"Delivery" = "Teslimat"; + +/* No comment provided by engineer. */ +"Delivery receipts are disabled!" = "Mesaj gönderim bilgisi devre dışı!"; + +/* No comment provided by engineer. */ +"Delivery receipts!" = "Mesaj gönderildi bilgisi!"; + +/* No comment provided by engineer. */ +"Description" = "Açıklama"; + +/* No comment provided by engineer. */ +"Desktop address" = "Bilgisayar adresi"; + +/* No comment provided by engineer. */ +"Desktop app version %@ is not compatible with this app." = "Masaüstü uygulaması sürümü %@ bu uygulama ile uyumlu değildir."; + +/* No comment provided by engineer. */ +"Desktop devices" = "Bilgisayar cihazları"; + +/* No comment provided by engineer. */ +"Develop" = "Geliştir"; + +/* No comment provided by engineer. */ +"Developer tools" = "Geliştirici araçları"; + +/* No comment provided by engineer. */ +"Device" = "Cihaz"; + +/* No comment provided by engineer. */ +"Device authentication is disabled. Turning off SimpleX Lock." = "Cihaz kimlik doğrulaması devre dışı. SimpleX Kilidi kapatılıyor."; + +/* No comment provided by engineer. */ +"Device authentication is not enabled. You can turn on SimpleX Lock via Settings, once you enable device authentication." = "Cihaz kimlik doğrulaması etkin değil. Cihaz kimlik doğrulamasını etkinleştirdikten sonra SimpleX Kilidini Ayarlar üzerinden açabilirsiniz."; + +/* No comment provided by engineer. */ +"different migration in the app/database: %@ / %@" = "uygulamada/veritabanında farklı geçiş: %@ / %@"; + +/* No comment provided by engineer. */ +"Different names, avatars and transport isolation." = "Farklı isimler, profil fotoğrafları ve taşıma izolasyonu."; + +/* connection level description */ +"direct" = "doğrudan"; + +/* chat feature */ +"Direct messages" = "Doğrudan mesajlar"; + +/* No comment provided by engineer. */ +"Direct messages between members are prohibited in this group." = "Bu grupta üyeler arasında direkt mesajlaşma yasaktır."; + +/* No comment provided by engineer. */ +"Disable (keep overrides)" = "Devre dışı bırak (geçersiz kılmaları koru)"; + +/* No comment provided by engineer. */ +"Disable for all" = "Herkes için devre dışı bırak"; + +/* authentication reason */ +"Disable SimpleX Lock" = "SimpleX Kilidini devre dışı bırak"; + +/* No comment provided by engineer. */ +"disabled" = "devre dışı"; + +/* No comment provided by engineer. */ +"Disappearing message" = "Kaybolan mesaj"; + +/* chat feature */ +"Disappearing messages" = "Kaybolan mesajlar"; + +/* No comment provided by engineer. */ +"Disappearing messages are prohibited in this chat." = "Kaybolan mesajlar bu sohbette yasaklanmış."; + +/* No comment provided by engineer. */ +"Disappearing messages are prohibited in this group." = "Kaybolan mesajlar bu grupta yasaklanmış."; + +/* No comment provided by engineer. */ +"Disappears at" = "da kaybolur"; + +/* copied message info */ +"Disappears at: %@" = "%@ da kaybolur"; + +/* server test step */ +"Disconnect" = "Bağlantıyı kes"; + +/* No comment provided by engineer. */ +"Disconnect desktop?" = "Bilgisayarla bağlantı kesilsin mi?"; + +/* No comment provided by engineer. */ +"Discover and join groups" = "Keşfet ve gruplara katıl"; + +/* No comment provided by engineer. */ +"Discover via local network" = "Yerel ağ aracılığıyla keşfet"; + +/* No comment provided by engineer. */ +"Do it later" = "Sonra yap"; + +/* No comment provided by engineer. */ +"Do NOT use SimpleX for emergency calls." = "Acil aramalar için SimpleX'i KULLANMAYIN."; + +/* No comment provided by engineer. */ +"Don't create address" = "Adres oluşturma"; + +/* No comment provided by engineer. */ +"Don't enable" = "Etkinleştirme"; + +/* No comment provided by engineer. */ +"Don't show again" = "Yeniden gösterme"; + +/* No comment provided by engineer. */ +"Downgrade and open chat" = "Sürüm düşür ve sohbeti aç"; + +/* server test step */ +"Download file" = "Dosya indir"; + +/* No comment provided by engineer. */ +"Duplicate display name!" = "Yinelenen görünen ad!"; + +/* integrity error chat item */ +"duplicate message" = "yinelenen mesaj"; + +/* No comment provided by engineer. */ +"Duration" = "Süre"; + +/* No comment provided by engineer. */ +"e2e encrypted" = "uçtan uca şifrelenmiş"; + +/* chat item action */ +"Edit" = "Düzenle"; + +/* No comment provided by engineer. */ +"Edit group profile" = "Grup profilini düzenle"; + +/* No comment provided by engineer. */ +"Enable" = "Etkinleştir"; + +/* No comment provided by engineer. */ +"Enable (keep overrides)" = "Etkinleştir (geçersiz kılmaları koru)"; + +/* No comment provided by engineer. */ +"Enable automatic message deletion?" = "Otomatik mesaj silme etkinleştirilsin mi?"; + +/* No comment provided by engineer. */ +"Enable camera access" = "Kamera erişimini etkinleştir"; + +/* No comment provided by engineer. */ +"Enable for all" = "Herkes için etkinleştir"; + +/* No comment provided by engineer. */ +"Enable instant notifications?" = "Anlık bildirimler etkinleştirilsin mi?"; + +/* No comment provided by engineer. */ +"Enable lock" = "Kilidi etkinleştir"; + +/* No comment provided by engineer. */ +"Enable notifications" = "Bildirimleri etkinleştir"; + +/* No comment provided by engineer. */ +"Enable periodic notifications?" = "Periyodik bildirimler etkinleştirilsin mi?"; + +/* No comment provided by engineer. */ +"Enable self-destruct" = "Kendini imhayı etkinleştir"; + +/* set passcode view */ +"Enable self-destruct passcode" = "Kendini imha şifresini etkinleştir"; + +/* authentication reason */ +"Enable SimpleX Lock" = "SimpleX Kilidini etkinleştir"; + +/* No comment provided by engineer. */ +"Enable TCP keep-alive" = "TCP canlı tutmayı etkinleştir"; + +/* enabled status */ +"enabled" = "etkin"; + +/* enabled status */ +"enabled for contact" = "konuşulan kişi için etkinleşti"; + +/* enabled status */ +"enabled for you" = "senin için etkinleştirildi"; + +/* No comment provided by engineer. */ +"Encrypt" = "Şifreleme"; + +/* No comment provided by engineer. */ +"Encrypt database?" = "Veritabanı şifrelensin mi?"; + +/* No comment provided by engineer. */ +"Encrypt local files" = "Yerel dosyaları şifrele"; + +/* No comment provided by engineer. */ +"Encrypt stored files & media" = "Saklanan dosyaları ve medyayı şifreleyin"; + +/* No comment provided by engineer. */ +"Encrypted database" = "Şifrelenmiş veritabanı"; + +/* notification */ +"Encrypted message or another event" = "Şifrelenmiş mesaj veya başka bir etkinlik"; + +/* notification */ +"Encrypted message: app is stopped" = "Şifrelenmiş mesaj: uygulama durdu"; + +/* notification */ +"Encrypted message: database error" = "Şifrelenmiş mesaj: veritabanı hatası"; + +/* notification */ +"Encrypted message: database migration error" = "Şifrelenmiş mesaj: veritabanı taşıma hatası"; + +/* notification */ +"Encrypted message: keychain error" = "Şifrelenmiş mesaj: Anahtar Zinciri hatası"; + +/* notification */ +"Encrypted message: no passphrase" = "Şifrelenmiş mesaj: parola yok"; + +/* notification */ +"Encrypted message: unexpected error" = "Şifrelenmiş mesaj: beklenmeyen hata"; + +/* chat item text */ +"encryption agreed" = "şifreleme kabul edildi"; + +/* chat item text */ +"encryption agreed for %@" = "şifreleme %@ için kabul edildi"; + +/* chat item text */ +"encryption ok" = "şifreleme etkin"; + +/* chat item text */ +"encryption ok for %@" = "şifreleme %@ için etkin"; + +/* chat item text */ +"encryption re-negotiation allowed" = "şifrelemenin yeniden anlaşmasına izin verildi"; + +/* chat item text */ +"encryption re-negotiation allowed for %@" = "şifrelemenin yeniden anlaşmasına %@ için izin verildi"; + +/* message decrypt error item */ +"Encryption re-negotiation error" = "Şifreleme yeniden anlaşma hatası"; + +/* No comment provided by engineer. */ +"Encryption re-negotiation failed." = "Şifreleme yeniden anlaşma başarısız oldu."; + +/* chat item text */ +"encryption re-negotiation required" = "şifrelemenin yeniden anlaşması gerekiyor"; + +/* chat item text */ +"encryption re-negotiation required for %@" = "şifrelemenin yeniden anlaşması %@ için gerekiyor"; + +/* No comment provided by engineer. */ +"ended" = "bitti"; + +/* call status */ +"ended call %@" = "%@ araması bitti"; + +/* No comment provided by engineer. */ +"Enter correct passphrase." = "Doğru şifreyi gir."; + +/* No comment provided by engineer. */ +"Enter group name…" = "Grup adı gir…"; + +/* No comment provided by engineer. */ +"Enter Passcode" = "Şifre gir"; + +/* No comment provided by engineer. */ +"Enter passphrase…" = "Parola gir…"; + +/* No comment provided by engineer. */ +"Enter password above to show!" = "Göstermek için yukarıdaki şifreyi gir!"; + +/* No comment provided by engineer. */ +"Enter server manually" = "Sunucuya manuel olarak gir"; + +/* No comment provided by engineer. */ +"Enter this device name…" = "Bu cihazın adını gir…"; + +/* placeholder */ +"Enter welcome message…" = "Hoşgeldin mesajı gir…"; + +/* placeholder */ +"Enter welcome message… (optional)" = "Hoşgeldin mesajı gir... (opsiyonel)"; + +/* No comment provided by engineer. */ +"Enter your name…" = "Adını gir…"; + +/* No comment provided by engineer. */ +"error" = "hata"; + +/* No comment provided by engineer. */ +"Error" = "Hata"; + +/* No comment provided by engineer. */ +"Error aborting address change" = "Adres değişikliği iptal edilirken hata oluştu"; + +/* No comment provided by engineer. */ +"Error accepting contact request" = "Bağlantı isteği kabul edilirken hata oluştu"; + +/* No comment provided by engineer. */ +"Error accessing database file" = "Veritabanı dosyasına erişilirken hata oluştu"; + +/* No comment provided by engineer. */ +"Error adding member(s)" = "Üye(ler) eklenirken hata oluştu"; + +/* No comment provided by engineer. */ +"Error changing address" = "Adres değiştirilirken hata oluştu"; + +/* No comment provided by engineer. */ +"Error changing role" = "Rol değiştirilirken hata oluştu"; + +/* No comment provided by engineer. */ +"Error changing setting" = "Ayar değiştirilirken hata oluştu"; + +/* No comment provided by engineer. */ +"Error creating address" = "Adres oluşturulurken hata oluştu"; + +/* No comment provided by engineer. */ +"Error creating group" = "Grup oluşturulurken hata oluştu"; + +/* No comment provided by engineer. */ +"Error creating group link" = "Grup bağlantısı oluşturulurken hata oluştu"; + +/* No comment provided by engineer. */ +"Error creating member contact" = "Kişi iletişimi oluşturulurken hata oluştu"; + +/* No comment provided by engineer. */ +"Error creating profile!" = "Profil oluşturulurken hata oluştu!"; + +/* No comment provided by engineer. */ +"Error decrypting file" = "Dosya şifresi çözülürken hata oluştu"; + +/* No comment provided by engineer. */ +"Error deleting chat database" = "Sohbet veritabanı silinirken sorun oluştu"; + +/* No comment provided by engineer. */ +"Error deleting chat!" = "Sohbet silinirken hata oluştu!"; + +/* No comment provided by engineer. */ +"Error deleting connection" = "Bağlantı silinirken hata oluştu"; + +/* No comment provided by engineer. */ +"Error deleting contact" = "Kişi silinirken hata oluştu"; + +/* No comment provided by engineer. */ +"Error deleting database" = "Veritabanı silinirken hata oluştu"; + +/* No comment provided by engineer. */ +"Error deleting old database" = "Eski veritabanı silinirken hata oluştu"; + +/* No comment provided by engineer. */ +"Error deleting token" = "Token silinirken hata oluştu"; + +/* No comment provided by engineer. */ +"Error deleting user profile" = "Kullanıcı profili silinirken hata oluştu"; + +/* No comment provided by engineer. */ +"Error enabling delivery receipts!" = "Görüldü bilgisi etkinleştirilirken hata oluştu!"; + +/* No comment provided by engineer. */ +"Error enabling notifications" = "Bildirimler etkinleştirilirken hata oluştu"; + +/* No comment provided by engineer. */ +"Error encrypting database" = "Veritabanı şifrelemesi çözülürken hata oluştu"; + +/* No comment provided by engineer. */ +"Error exporting chat database" = "Sohbet veritabanı dışa aktarılırken hata oluştu"; + +/* No comment provided by engineer. */ +"Error importing chat database" = "Sohbet veritabanı içe aktarılırken hata oluştu"; + +/* No comment provided by engineer. */ +"Error joining group" = "Gruba katılırken hata oluştu"; + +/* No comment provided by engineer. */ +"Error loading %@ servers" = "%@ sunucuları yüklenirken hata oluştu"; + +/* No comment provided by engineer. */ +"Error opening chat" = "Sohbeti açarken sorun oluştu"; + +/* No comment provided by engineer. */ +"Error receiving file" = "Dosya alınırken sorun oluştu"; + +/* No comment provided by engineer. */ +"Error removing member" = "Kişiyi silerken sorun oluştu"; + +/* No comment provided by engineer. */ +"Error saving %@ servers" = "%@ sunucuları kaydedilirken sorun oluştu"; + +/* No comment provided by engineer. */ +"Error saving group profile" = "Grup profili kaydedilirken sorun oluştu"; + +/* No comment provided by engineer. */ +"Error saving ICE servers" = "ICE sunucularını kaydedirken sorun oluştu"; + +/* No comment provided by engineer. */ +"Error saving passcode" = "Parola kaydedilirken sorun oluştu"; + +/* No comment provided by engineer. */ +"Error saving passphrase to keychain" = "Parolayı Anahtar Zincirine kaydederken hata oluştu"; + +/* No comment provided by engineer. */ +"Error saving user password" = "Kullanıcı şifresi kaydedilirken hata oluştu"; + +/* No comment provided by engineer. */ +"Error scanning code: %@" = "Kod taranırken hata oluştu: %@"; + +/* No comment provided by engineer. */ +"Error sending email" = "Eposta gönderilirken hata oluştu"; + +/* No comment provided by engineer. */ +"Error sending member contact invitation" = "Kişi iletişim daveti gönderilirken hata oluştu"; + +/* No comment provided by engineer. */ +"Error sending message" = "Mesaj gönderilirken hata oluştu"; + +/* No comment provided by engineer. */ +"Error setting delivery receipts!" = "Görüldü ayarlanırken hata oluştu!"; + +/* No comment provided by engineer. */ +"Error starting chat" = "Sohbet başlatılırken hata oluştu"; + +/* No comment provided by engineer. */ +"Error stopping chat" = "Sohbet durdurulurken hata oluştu"; + +/* No comment provided by engineer. */ +"Error switching profile!" = "Profil değiştirilirken hata oluştu!"; + +/* No comment provided by engineer. */ +"Error synchronizing connection" = "Bağlantı senkronizasyonunda hata oluştu"; + +/* No comment provided by engineer. */ +"Error updating group link" = "Grup bağlantısı güncellenirken hata oluştu"; + +/* No comment provided by engineer. */ +"Error updating message" = "Mesaj güncellenirken hata oluştu"; + +/* No comment provided by engineer. */ +"Error updating settings" = "Ayarları güncellerken hata oluştu"; + +/* No comment provided by engineer. */ +"Error updating user privacy" = "Kullanıcı gizliliği güncellenirken hata oluştu"; + +/* No comment provided by engineer. */ +"Error: " = "Hata: "; + +/* No comment provided by engineer. */ +"Error: %@" = "Hata: %@"; + +/* No comment provided by engineer. */ +"Error: no database file" = "Hata: veritabanı dosyası yok"; + +/* No comment provided by engineer. */ +"Error: URL is invalid" = "Hata: URL geçersiz"; + +/* No comment provided by engineer. */ +"Even when disabled in the conversation." = "Konuşma sırasında devre dışı bırakılsa bile."; + +/* No comment provided by engineer. */ +"event happened" = "etkinliği yaşandı"; + +/* No comment provided by engineer. */ +"Exit without saving" = "Kaydetmeden çık"; + +/* chat item action */ +"Expand" = "Genişlet"; + +/* No comment provided by engineer. */ +"Export database" = "Veritabanını dışarı aktar"; + +/* No comment provided by engineer. */ +"Export error:" = "Dışarı çıkarma hatası:"; + +/* No comment provided by engineer. */ +"Exported database archive." = "Dışarı çıkarılmış veritabanı arşivi."; + +/* No comment provided by engineer. */ +"Exporting database archive…" = "Dışarı çıkarılmış veritabanı arşivi…"; + +/* No comment provided by engineer. */ +"Failed to remove passphrase" = "Parola kaldırılamadı"; + +/* No comment provided by engineer. */ +"Fast and no wait until the sender is online!" = "Hızlı ve gönderici çevrimiçi olana kadar beklemek yok!"; + +/* No comment provided by engineer. */ +"Faster joining and more reliable messages." = "Daha hızlı katılma ve daha güvenilir mesajlar."; + +/* No comment provided by engineer. */ +"Favorite" = "Favori"; + +/* No comment provided by engineer. */ +"File will be deleted from servers." = "Dosya sunuculardan silinecek."; + +/* No comment provided by engineer. */ +"File will be received when your contact completes uploading it." = "Dosya kişi yüklemeyi tamamladığında alınacak."; + +/* No comment provided by engineer. */ +"File will be received when your contact is online, please wait or check later!" = "Dosya kişi çevrimiçi olduğunda alınacaktır, lütfen bekleyin veya daha sonra kontrol edin!"; + +/* No comment provided by engineer. */ +"File: %@" = "Dosya: %@"; + +/* No comment provided by engineer. */ +"Files & media" = "Dosyalar & medya"; + +/* chat feature */ +"Files and media" = "Dosyalar ve medya"; + +/* No comment provided by engineer. */ +"Files and media are prohibited in this group." = "Dosyalar ve medya bu grupta yasaklandı."; + +/* No comment provided by engineer. */ +"Files and media prohibited!" = "Dosyalar ve medya yasaklandı!"; + +/* No comment provided by engineer. */ +"Filter unread and favorite chats." = "Favori ve okunmamış sohbetleri filtrele."; + +/* No comment provided by engineer. */ +"Finally, we have them! 🚀" = "Sonunda, onlara sahibiz! 🚀"; + +/* No comment provided by engineer. */ +"Find chats faster" = "Sohbetleri daha hızlı bul"; + +/* No comment provided by engineer. */ +"Fix" = "Düzelt"; + +/* No comment provided by engineer. */ +"Fix connection" = "Bağlantıyı düzelt"; + +/* No comment provided by engineer. */ +"Fix connection?" = "Bağlantı düzeltilsin mi?"; + +/* No comment provided by engineer. */ +"Fix encryption after restoring backups." = "Yedekleri geri yükledikten sonra şifrelemeyi düzelt."; + +/* No comment provided by engineer. */ +"Fix not supported by contact" = "Düzeltme kişi tarafından desteklenmiyor"; + +/* No comment provided by engineer. */ +"Fix not supported by group member" = "Düzeltme grup üyesi tarafından desteklenmiyor"; + +/* No comment provided by engineer. */ +"For console" = "Konsol için"; + +/* No comment provided by engineer. */ +"Found desktop" = "Bilgisayar bulundu"; + +/* No comment provided by engineer. */ +"French interface" = "Fransızca arayüz"; + +/* No comment provided by engineer. */ +"Full link" = "Bütün bağlantı adresi"; + +/* No comment provided by engineer. */ +"Full name (optional)" = "Bütün isim (opsiyonel)"; + +/* No comment provided by engineer. */ +"Full name:" = "Bütün isim:"; + +/* No comment provided by engineer. */ +"Fully decentralized – visible only to members." = "Tamamiyle merkezi olmayan - sadece kişilere görünür."; + +/* No comment provided by engineer. */ +"Fully re-implemented - work in background!" = "Arkaplanda çalışma - tamamiyle yeniden yapıldı!"; + +/* No comment provided by engineer. */ +"Further reduced battery usage" = "Daha da azaltılmış pil kullanımı"; + +/* No comment provided by engineer. */ +"GIFs and stickers" = "GİFler ve çıkartmalar"; + +/* No comment provided by engineer. */ +"Group" = "Grup"; + +/* No comment provided by engineer. */ +"Group already exists" = "Grup çoktan mevcut"; + +/* No comment provided by engineer. */ +"Group already exists!" = "Grup çoktan mevcut!"; + +/* No comment provided by engineer. */ +"group deleted" = "grup silindi"; + +/* No comment provided by engineer. */ +"Group display name" = "Grup görünen adı"; + +/* No comment provided by engineer. */ +"Group full name (optional)" = "Grubun bütün ismi (opsiyonel)"; + +/* No comment provided by engineer. */ +"Group image" = "Grup fotoğrafı"; + +/* No comment provided by engineer. */ +"Group invitation" = "Grup daveti"; + +/* No comment provided by engineer. */ +"Group invitation expired" = "Grup davetinin süresi doldu"; + +/* No comment provided by engineer. */ +"Group invitation is no longer valid, it was removed by sender." = "Grup davet artık geçerli değil, gönderici tarafından silindi."; + +/* No comment provided by engineer. */ +"Group link" = "Grup bağlantısı"; + +/* No comment provided by engineer. */ +"Group links" = "Grup bağlantıları"; + +/* No comment provided by engineer. */ +"Group members can add message reactions." = "Grup üyeleri mesaj tepkileri ekleyebilir."; + +/* No comment provided by engineer. */ +"Group members can send direct messages." = "Grup üyeleri doğrudan mesajlar gönderebilir."; + +/* No comment provided by engineer. */ +"Group members can send disappearing messages." = "Grup üyeleri kaybolan mesajlar gönderebilir."; + +/* No comment provided by engineer. */ +"Group members can send files and media." = "Grup üyeleri dosyalar ve medya gönderebilir."; + +/* No comment provided by engineer. */ +"Group members can send voice messages." = "Grup üyeleri sesli mesajlar gönderebilir."; + +/* notification */ +"Group message:" = "Grup mesajı:"; + +/* No comment provided by engineer. */ +"Group moderation" = "Grup yöneticiliği"; + +/* No comment provided by engineer. */ +"Group preferences" = "Grup tercihleri"; + +/* No comment provided by engineer. */ +"Group profile" = "Grup profili"; + +/* No comment provided by engineer. */ +"Group profile is stored on members' devices, not on the servers." = "Grup profili üyelerin cihazlarında saklanır, sunucularda değil."; + +/* snd group event chat item */ +"group profile updated" = "grup profili güncellendi"; + +/* No comment provided by engineer. */ +"Group welcome message" = "Grup hoşgeldin mesajı"; + +/* No comment provided by engineer. */ +"Group will be deleted for all members - this cannot be undone!" = "Grup tüm üyelerden silinecektir - bu geri alınamaz!"; + +/* No comment provided by engineer. */ +"Group will be deleted for you - this cannot be undone!" = "Grup senden silinecektir - bu geri alınamaz!"; + +/* No comment provided by engineer. */ +"Help" = "Yardım"; + +/* No comment provided by engineer. */ +"Hidden" = "Gizlenmiş"; + +/* No comment provided by engineer. */ +"Hidden chat profiles" = "Gizlenmiş sohbet profilleri"; + +/* No comment provided by engineer. */ +"Hidden profile password" = "Gizlenmiş profil şifresi"; + +/* chat item action */ +"Hide" = "Gizle"; + +/* No comment provided by engineer. */ +"Hide app screen in the recent apps." = "Son uygulamalarda uygulama ekranını gizle."; + +/* No comment provided by engineer. */ +"Hide profile" = "Profili gizle"; + +/* No comment provided by engineer. */ +"Hide:" = "Gizle:"; + +/* No comment provided by engineer. */ +"History" = "Geçmiş"; + +/* time unit */ +"hours" = "saat"; + +/* No comment provided by engineer. */ +"How it works" = "Nasıl çalışıyor"; + +/* No comment provided by engineer. */ +"How SimpleX works" = "SimpleX nasıl çalışır"; + +/* No comment provided by engineer. */ +"How to" = "Nasıl yapılır"; + +/* No comment provided by engineer. */ +"How to use it" = "Nasıl kullanılır"; + +/* No comment provided by engineer. */ +"How to use your servers" = "Sunucularını nasıl kullanabilirsin"; + +/* No comment provided by engineer. */ +"ICE servers (one per line)" = "ICE sunucuları (her satıra bir tane)"; + +/* No comment provided by engineer. */ +"If you can't meet in person, show QR code in a video call, or share the link." = "Eğer onunla buluşamıyorsan görüntülü aramada QR kod göster veya bağlantığı paylaş."; + +/* No comment provided by engineer. */ +"If you enter this passcode when opening the app, all app data will be irreversibly removed!" = "Eğer bu şifreyi uygulamayı açarken girersen, bütün uygulama verileri geri dönülemeyen bir şekilde silinecektir!"; + +/* No comment provided by engineer. */ +"If you enter your self-destruct passcode while opening the app:" = "Uygulamayı açarken kendi kendini imha eden şifrenizi girerseniz:"; + +/* No comment provided by engineer. */ +"If you need to use the chat now tap **Do it later** below (you will be offered to migrate the database when you restart the app)." = "Sohbeti şimdi kullanmanız gerekiyorsa aşağıdaki **Daha sonra yap** seçeneğine dokunun (uygulamayı yeniden başlattığınızda veritabanını taşımanız önerilecektir)."; + +/* No comment provided by engineer. */ +"Ignore" = "Yok say"; + +/* No comment provided by engineer. */ +"Image will be received when your contact completes uploading it." = "Kişi yüklemeyi bitirdiğinde fotoğraf alınacaktır."; + +/* No comment provided by engineer. */ +"Image will be received when your contact is online, please wait or check later!" = "Kişi çevrimiçi olduğunda fotoğraf alınacaktır, lütfen bekleyin veya daha sonra kontrol et!"; + +/* No comment provided by engineer. */ +"Immediately" = "Hemen"; + +/* No comment provided by engineer. */ +"Immune to spam and abuse" = "Spam ve kötüye kullanıma karşı bağışıklı"; + +/* No comment provided by engineer. */ +"Import" = "İçe aktar"; + +/* No comment provided by engineer. */ +"Import chat database?" = "Sohbet veritabanı içe aktarılsın mı?"; + +/* No comment provided by engineer. */ +"Import database" = "Veritabanını içe aktar"; + +/* No comment provided by engineer. */ +"Improved privacy and security" = "Geliştirilmiş gizlilik ve güvenlik"; + +/* No comment provided by engineer. */ +"Improved server configuration" = "Geliştirilmiş sunucu yapılandırması"; + +/* No comment provided by engineer. */ +"In reply to" = "Cevap olarak"; + +/* No comment provided by engineer. */ +"Incognito" = "Gizli"; + +/* No comment provided by engineer. */ +"Incognito groups" = "Gizli gruplar"; + +/* No comment provided by engineer. */ +"Incognito mode" = "Gizli mod"; + +/* No comment provided by engineer. */ +"Incognito mode protects your privacy by using a new random profile for each contact." = "Gizli mod her kişiye farklı olarak rasgele profiller kullanarak gizliliğinizi korur."; + +/* chat list item description */ +"incognito via contact address link" = "kişi bağlantı linki aracılığıyla gizli"; + +/* chat list item description */ +"incognito via group link" = "grup bağlantısı aracılığıyla gizli"; + +/* chat list item description */ +"incognito via one-time link" = "tek seferlik bağlantısı aracılığıyla gizli"; + +/* notification */ +"Incoming audio call" = "Gelen sesli arama"; + +/* notification */ +"Incoming call" = "Gelen arama"; + +/* notification */ +"Incoming video call" = "Gelen görüntülü arama"; + +/* No comment provided by engineer. */ +"Incompatible database version" = "Uyumsuz veritabanı sürümü"; + +/* No comment provided by engineer. */ +"Incompatible version" = "Uyumsuz sürüm"; + +/* PIN entry */ +"Incorrect passcode" = "Uyumsuz parola"; + +/* No comment provided by engineer. */ +"Incorrect security code!" = "Uyumsuz güvenlik kodu!"; + +/* connection level description */ +"indirect (%d)" = "dolaylı (%d)"; + +/* chat item action */ +"Info" = "Bilgi"; + +/* No comment provided by engineer. */ +"Initial role" = "Başlangıç rolü"; + +/* No comment provided by engineer. */ +"Install [SimpleX Chat for terminal](https://github.com/simplex-chat/simplex-chat)" = "[Terminal için SimpleX Chat]i indir(https://github.com/simplex-chat/simplex-chat)"; + +/* No comment provided by engineer. */ +"Instant push notifications will be hidden!\n" = "Anlık bildirimler gizlenecek!\n"; + +/* No comment provided by engineer. */ +"Instantly" = "Anında"; + +/* No comment provided by engineer. */ +"Interface" = "Arayüz"; + +/* invalid chat data */ +"invalid chat" = "geçersi̇z sohbet"; + +/* No comment provided by engineer. */ +"invalid chat data" = "geçersi̇z sohbet verisi"; + +/* No comment provided by engineer. */ +"Invalid connection link" = "Geçersiz bağlanma bağlantısı"; + +/* invalid chat item */ +"invalid data" = "geçersiz veri"; + +/* No comment provided by engineer. */ +"Invalid link" = "Geçersiz bağlantı"; + +/* No comment provided by engineer. */ +"Invalid name!" = "Geçersiz isim!"; + +/* No comment provided by engineer. */ +"Invalid QR code" = "Geçersiz QR kodu"; + +/* No comment provided by engineer. */ +"Invalid response" = "Geçersiz yanıt"; + +/* No comment provided by engineer. */ +"Invalid server address!" = "Geçersiz sunucu adresi!"; + +/* item status text */ +"Invalid status" = "Geçersiz durum"; + +/* No comment provided by engineer. */ +"Invitation expired!" = "Davetin süresi geçti!"; + +/* group name */ +"invitation to group %@" = "%@ grubuna davet"; + +/* No comment provided by engineer. */ +"Invite friends" = "Arkadaşları davet et"; + +/* No comment provided by engineer. */ +"Invite members" = "Üyeleri davet et"; + +/* No comment provided by engineer. */ +"Invite to group" = "Gruba davet et"; + +/* No comment provided by engineer. */ +"invited" = "davet edildi"; + +/* rcv group event chat item */ +"invited %@" = "%@ a davet edildi"; + +/* chat list item title */ +"invited to connect" = "bağlanmaya davet edildi"; + +/* rcv group event chat item */ +"invited via your group link" = "grup bağlantınız üzerinden davet edildi"; + +/* No comment provided by engineer. */ +"iOS Keychain is used to securely store passphrase - it allows receiving push notifications." = "iOS Anahtar Zinciri parolayı güvenli bir şekilde saklamak için kullanılır - anlık bildirimlerin alınmasını sağlar."; + +/* 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 Anahtar Zinciri, uygulamayı yeniden başlattıktan veya parolayı değiştirdikten sonra parolayı güvenli bir şekilde saklamak için kullanılacaktır - anlık bildirimlerin alınmasına izin verecektir."; + +/* No comment provided by engineer. */ +"Irreversible message deletion" = "Geri dönülemeyen mesaj silimi"; + +/* No comment provided by engineer. */ +"Irreversible message deletion is prohibited in this chat." = "Bu sohbette geri döndürülemez mesaj silme yasaktır."; + +/* No comment provided by engineer. */ +"Irreversible message deletion is prohibited in this group." = "Bu grupta geri döndürülemez mesaj silme yasaktır."; + +/* No comment provided by engineer. */ +"It allows having many anonymous connections without any shared data between them in a single chat profile." = "Tek bir sohbet profilinde aralarında herhangi bir veri paylaşımı olmadan birçok anonim bağlantıya sahip olmaya izin verir."; + +/* No comment provided by engineer. */ +"It can happen when you or your connection used the old database backup." = "Siz veya bağlantınız eski veritabanı yedeğini kullandığında bu durum ortaya çıkabilir."; + +/* No comment provided by engineer. */ +"It can happen when:\n1. The messages expired in the sending client after 2 days or on the server after 30 days.\n2. Message decryption failed, because you or your contact used old database backup.\n3. The connection was compromised." = "Şu durumlarda ortaya çıkabilir:\n1. Mesajların gönderici istemcide 2 gün sonra veya sunucuda 30 gün sonra süresi dolmuştur.\n2. Siz veya kişi eski veritabanı yedeği kullandığı için mesaj şifre çözme işlemi başarısız olmuştur.\n3. Bağlantı tehlikeye girmiştir."; + +/* No comment provided by engineer. */ +"It seems like you are already connected via this link. If it is not the case, there was an error (%@)." = "Bu bağlantı üzerinden zaten bağlanmışsınız gibi görünüyor. Eğer durum böyle değilse, bir hata oluştu (%@)."; + +/* No comment provided by engineer. */ +"Italian interface" = "İtalyanca arayüz"; + +/* No comment provided by engineer. */ +"italic" = "italik"; + +/* No comment provided by engineer. */ +"Japanese interface" = "Japonca arayüz"; + +/* No comment provided by engineer. */ +"Join" = "Katıl"; + +/* No comment provided by engineer. */ +"join as %@" = "%@ olarak katıl"; + +/* No comment provided by engineer. */ +"Join group" = "Gruba katıl"; + +/* No comment provided by engineer. */ +"Join group?" = "Gruba katılınsın mı?"; + +/* No comment provided by engineer. */ +"Join incognito" = "Gizli katıl"; + +/* No comment provided by engineer. */ +"Join with current profile" = "Şu anki profille katıl"; + +/* No comment provided by engineer. */ +"Join your group?\nThis is your link for group %@!" = "Bu gruba katılınsın mı?\nBu senin grup için bağlantın %@!"; + +/* No comment provided by engineer. */ +"Joining group" = "Gruba katılınıyor"; + +/* No comment provided by engineer. */ +"Keep" = "Tut"; + +/* No comment provided by engineer. */ +"Keep the app open to use it from desktop" = "Bilgisayardan kullanmak için uygulamayı açık tut"; + +/* No comment provided by engineer. */ +"Keep unused invitation?" = "Kullanılmamış davet tutulsun mu?"; + +/* No comment provided by engineer. */ +"Keep your connections" = "Bağlantılarınızı koruyun"; + +/* No comment provided by engineer. */ +"Keychain error" = "Anahtar Zinciri hatası"; + +/* No comment provided by engineer. */ +"KeyChain error" = "Anahtar Zinciri hatası"; + +/* No comment provided by engineer. */ +"Large file!" = "Büyük dosya!"; + +/* No comment provided by engineer. */ +"Learn more" = "Daha fazlası"; + +/* No comment provided by engineer. */ +"Leave" = "Ayrıl"; + +/* No comment provided by engineer. */ +"Leave group" = "Gruptan ayrıl"; + +/* No comment provided by engineer. */ +"Leave group?" = "Gruptan çıkılsın mı?"; + +/* rcv group event chat item */ +"left" = "ayrıldı"; + +/* email subject */ +"Let's talk in SimpleX Chat" = "Hadi SimpleX Chat'te konuşalım"; + +/* No comment provided by engineer. */ +"Light" = "Açık"; + +/* No comment provided by engineer. */ +"Limitations" = "Sınırlamalar"; + +/* No comment provided by engineer. */ +"Link mobile and desktop apps! 🔗" = "Telefon ve bilgisayar uygulamalarını bağla! 🔗"; + +/* No comment provided by engineer. */ +"Linked desktop options" = "Bağlanmış bilgisayar ayarları"; + +/* No comment provided by engineer. */ +"Linked desktops" = "Bağlanmış bilgisayarlar"; + +/* No comment provided by engineer. */ +"LIVE" = "CANLI"; + +/* No comment provided by engineer. */ +"Live message!" = "Canlı mesaj!"; + +/* No comment provided by engineer. */ +"Live messages" = "Canlı mesajlar"; + +/* No comment provided by engineer. */ +"Local" = "Yerel"; + +/* No comment provided by engineer. */ +"Local name" = "Yerel isim"; + +/* No comment provided by engineer. */ +"Local profile data only" = "Sadece yerel profil verisi"; + +/* No comment provided by engineer. */ +"Lock after" = "Sonra kilitle"; + +/* No comment provided by engineer. */ +"Lock mode" = "Kilit modu"; + +/* No comment provided by engineer. */ +"Make a private connection" = "Gizli bir bağlantı oluştur"; + +/* No comment provided by engineer. */ +"Make one message disappear" = "Bir mesajın kaybolmasını sağlayın"; + +/* No comment provided by engineer. */ +"Make profile private!" = "Profili gizli yap!"; + +/* No comment provided by engineer. */ +"Make sure %@ server addresses are in correct format, line separated and are not duplicated (%@)." = "%@ sunucu adreslerinin doğru formatta olduğundan, satır ayrımı yapıldığından ve yinelenmediğinden (%@) emin olun."; + +/* No comment provided by engineer. */ +"Make sure WebRTC ICE server addresses are in correct format, line separated and are not duplicated." = "WebRTC ICE sunucu adreslerinin doğru formatta olduğundan, satırlara ayrıldığından ve yinelenmediğinden emin olun."; + +/* No comment provided by engineer. */ +"Many people asked: *if SimpleX has no user identifiers, how can it deliver messages?*" = "Çoğu kişi sordu: *eğer SimpleX'in hiç kullanıcı tanımlayıcıları yok, o zaman mesajları nasıl gönderebiliyor?*"; + +/* No comment provided by engineer. */ +"Mark deleted for everyone" = "Herkes için silinmiş olarak işaretle"; + +/* No comment provided by engineer. */ +"Mark read" = "Okunmuş olarak işaretle"; + +/* No comment provided by engineer. */ +"Mark verified" = "Onaylanmış olarak işaretle"; + +/* No comment provided by engineer. */ +"Markdown in messages" = "Mesajlarda işaretleme"; + +/* marked deleted chat item preview text */ +"marked deleted" = "silinmiş olarak işaretlenmiş"; + +/* No comment provided by engineer. */ +"Max 30 seconds, received instantly." = "Maksimum 30 saniye, anında alındı."; + +/* member role */ +"member" = "üye"; + +/* No comment provided by engineer. */ +"Member" = "Kişi"; + +/* rcv group event chat item */ +"member connected" = "bağlanıldı"; + +/* No comment provided by engineer. */ +"Member role will be changed to \"%@\". All group members will be notified." = "Üye rolü \"%@\" olarak değiştirilecektir. Ve tüm grup üyeleri bilgilendirilecektir."; + +/* No comment provided by engineer. */ +"Member role will be changed to \"%@\". The member will receive a new invitation." = "Üye rolü \"%@\" olarak değiştirilecektir. Ve üye yeni bir davetiye alacaktır."; + +/* No comment provided by engineer. */ +"Member will be removed from group - this cannot be undone!" = "Üye gruptan çıkarılacaktır - bu geri alınamaz!"; + +/* item status text */ +"Message delivery error" = "Mesaj gönderim hatası"; + +/* No comment provided by engineer. */ +"Message delivery receipts!" = "Mesaj alındı bilgisi!"; + +/* No comment provided by engineer. */ +"Message draft" = "Mesaj taslağı"; + +/* chat feature */ +"Message reactions" = "Mesaj tepkileri"; + +/* No comment provided by engineer. */ +"Message reactions are prohibited in this chat." = "Mesaj tepkileri bu sohbette yasaklandı."; + +/* No comment provided by engineer. */ +"Message reactions are prohibited in this group." = "Mesaj tepkileri bu grupta yasaklandı."; + +/* notification */ +"message received" = "mesaj alındı"; + +/* No comment provided by engineer. */ +"Message text" = "Mesaj yazısı"; + +/* No comment provided by engineer. */ +"Messages" = "Mesajlar"; + +/* No comment provided by engineer. */ +"Messages & files" = "Mesajlar & dosyalar"; + +/* No comment provided by engineer. */ +"Messages from %@ will be shown!" = "%@ den gelen mesajlar gösterilecektir!"; + +/* No comment provided by engineer. */ +"Migrating database archive…" = "Veritabanı arşivine geçiliyor…"; + +/* No comment provided by engineer. */ +"Migration error:" = "Geçiş hatası:"; + +/* No comment provided by engineer. */ +"Migration failed. Tap **Skip** below to continue using the current database. Please report the issue to the app developers via chat or email [chat@simplex.chat](mailto:chat@simplex.chat)." = "Geçiş başarısız oldu. Alttaki **Geç** tuşuna basarak şu anki veritabanını kullanabilirsiniz. Lütfen sorunu sohbet veya e-posta yoluyla uygulama geliştiricilerine bildirin[chat@simplex.chat](mailto:chat@simplex.chat)."; + +/* No comment provided by engineer. */ +"Migration is completed" = "Geçiş tamamlandı"; + +/* No comment provided by engineer. */ +"Migrations: %@" = "Geçişler: %@"; + +/* time unit */ +"minutes" = "dakikalar"; + +/* call status */ +"missed call" = "cevapsız arama"; + +/* chat item action */ +"Moderate" = "Yönet"; + +/* moderated chat item */ +"moderated" = "yönetildi"; + +/* No comment provided by engineer. */ +"Moderated at" = "de yönetildi"; + +/* copied message info */ +"Moderated at: %@" = "%@ de yönetildi"; + +/* No comment provided by engineer. */ +"moderated by %@" = "%@ tarafından yönetilmekte"; + +/* time unit */ +"months" = "aylar"; + +/* No comment provided by engineer. */ +"More improvements are coming soon!" = "Daha fazla geliştirmeler yakında geliyor!"; + +/* item status description */ +"Most likely this connection is deleted." = "Büyük ihtimalle bu bağlantı silinmiş."; + +/* No comment provided by engineer. */ +"Most likely this contact has deleted the connection with you." = "Büyük ihtimalle bu kişi seninle bağlantını sildi."; + +/* No comment provided by engineer. */ +"Multiple chat profiles" = "Çoklu sohbet profili"; + +/* No comment provided by engineer. */ +"Mute" = "Sustur"; + +/* No comment provided by engineer. */ +"Muted when inactive!" = "Aktif değilken susturuldu!"; + +/* No comment provided by engineer. */ +"Name" = "İsim"; + +/* No comment provided by engineer. */ +"Network & servers" = "Ağ & sunucular"; + +/* No comment provided by engineer. */ +"Network settings" = "Ağ ayarları"; + +/* No comment provided by engineer. */ +"Network status" = "Ağ durumu"; + +/* No comment provided by engineer. */ +"never" = "asla"; + +/* No comment provided by engineer. */ +"New chat" = "Yeni sohbet"; + +/* notification */ +"New contact request" = "Yeni bağlantı isteği"; + +/* notification */ +"New contact:" = "Yeni kişi:"; + +/* No comment provided by engineer. */ +"New database archive" = "Yeni veritabanı arşivi"; + +/* No comment provided by engineer. */ +"New desktop app!" = "Yeni bilgisayar uygulaması!"; + +/* No comment provided by engineer. */ +"New display name" = "Yeni görünen ad"; + +/* No comment provided by engineer. */ +"New in %@" = "%@ da yeni"; + +/* No comment provided by engineer. */ +"New member role" = "Yeni üye rolü"; + +/* notification */ +"new message" = "yeni mesaj"; + +/* notification */ +"New message" = "Yeni mesaj"; + +/* No comment provided by engineer. */ +"New Passcode" = "Yeni şifre"; + +/* No comment provided by engineer. */ +"New passphrase…" = "Yeni parola…"; + +/* pref value */ +"no" = "hayır"; + +/* No comment provided by engineer. */ +"No" = "Hayır"; + +/* Authentication unavailable */ +"No app password" = "Uygulama şifresi yok"; + +/* No comment provided by engineer. */ +"No contacts selected" = "Hiçbir kişi seçilmedi"; + +/* No comment provided by engineer. */ +"No contacts to add" = "Eklenecek kişi yok"; + +/* No comment provided by engineer. */ +"No delivery information" = "Gönderim bilgisi yok"; + +/* No comment provided by engineer. */ +"No device token!" = "Cihaz tokeni yok!"; + +/* No comment provided by engineer. */ +"no e2e encryption" = "uçtan uca şifreleme yok"; + +/* No comment provided by engineer. */ +"No filtered chats" = "Filtrelenmiş sohbetler yok"; + +/* No comment provided by engineer. */ +"No group!" = "Grup bulunamadı!"; + +/* No comment provided by engineer. */ +"No history" = "Geçmiş yok"; + +/* No comment provided by engineer. */ +"No permission to record voice message" = "Sesli mesaj kaydetmek için izin yok"; + +/* No comment provided by engineer. */ +"No received or sent files" = "Hiç alınmış veya gönderilmiş dosya yok"; + +/* copied message info in history */ +"no text" = "metin yok"; + +/* No comment provided by engineer. */ +"Not compatible!" = "Uyumlu değil!"; + +/* No comment provided by engineer. */ +"Notifications" = "Bildirimler"; + +/* No comment provided by engineer. */ +"Notifications are disabled!" = "Bildirimler devre dışı!"; + +/* No comment provided by engineer. */ +"Now admins can:\n- delete members' messages.\n- disable members (\"observer\" role)" = "Şimdi yöneticiler:\n- üyelerin mesajlarını silebilir\n- üyeleri devre dışı bırakabilir (\"gözlemci\" rolü)"; + +/* member role */ +"observer" = "gözlemci"; + +/* enabled status + group pref value + time to disappear */ +"off" = "kapalı"; + +/* No comment provided by engineer. */ +"Off" = "Kapalı"; + +/* feature offered item */ +"offered %@" = "%@ teklif edildi"; + +/* feature offered item */ +"offered %@: %@" = "%1$@: %2$@ teklif etti"; + +/* No comment provided by engineer. */ +"Ok" = "Tamam"; + +/* No comment provided by engineer. */ +"OK" = "TAMAM"; + +/* No comment provided by engineer. */ +"Old database" = "Eski veritabanı"; + +/* No comment provided by engineer. */ +"Old database archive" = "Eski veritabanı arşivi"; + +/* group pref value */ +"on" = "açık"; + +/* No comment provided by engineer. */ +"One-time invitation link" = "Tek zamanlı bağlantı daveti"; + +/* No comment provided by engineer. */ +"Onion hosts will be required for connection. Requires enabling VPN." = "Bağlantı için Onion ana bilgisayarları gerekecektir. VPN'nin etkinleştirilmesi gerekir."; + +/* No comment provided by engineer. */ +"Onion hosts will be used when available. Requires enabling VPN." = "Onion ana bilgisayarları mevcutsa kullanılacaktır. VPN'nin etkinleştirilmesi gerekir."; + +/* No comment provided by engineer. */ +"Onion hosts will not be used." = "Onion ana bilgisayarları kullanılmayacaktır."; + +/* No comment provided by engineer. */ +"Only client devices store user profiles, contacts, groups, and messages sent with **2-layer end-to-end encryption**." = "Yalnızca istemci cihazlar kullanıcı profillerini, kişileri, grupları ve **2 katmanlı uçtan uca şifreleme** ile gönderilen mesajları depolar."; + +/* No comment provided by engineer. */ +"Only group owners can change group preferences." = "Grup tercihlerini yalnızca grup sahipleri değiştirebilir."; + +/* No comment provided by engineer. */ +"Only group owners can enable files and media." = "Yalnızca grup sahipleri dosyaları ve medyayı etkinleştirebilir."; + +/* No comment provided by engineer. */ +"Only group owners can enable voice messages." = "Yalnızca grup sahipleri sesli mesajları etkinleştirebilir."; + +/* No comment provided by engineer. */ +"Only you can add message reactions." = "Sadece siz mesaj tepkileri ekleyebilirsiniz."; + +/* No comment provided by engineer. */ +"Only you can make calls." = "Sadece sen aramalar yapabilirsin."; + +/* No comment provided by engineer. */ +"Only you can send disappearing messages." = "Sadece sen kaybolan mesajlar gönderebilirsin."; + +/* No comment provided by engineer. */ +"Only you can send voice messages." = "Sadece sen sesli mesajlar gönderebilirsin."; + +/* No comment provided by engineer. */ +"Only your contact can add message reactions." = "Sadece karşıdaki kişi mesaj tepkileri ekleyebilir."; + +/* No comment provided by engineer. */ +"Only your contact can make calls." = "Sadece karşıdaki kişi aramalar yapabilir."; + +/* No comment provided by engineer. */ +"Only your contact can send disappearing messages." = "Sadece karşıdaki kişi kaybolan mesajlar gönderebilir."; + +/* No comment provided by engineer. */ +"Only your contact can send voice messages." = "Sadece karşıdaki kişi sesli mesajlar gönderebilir."; + +/* No comment provided by engineer. */ +"Open" = "Aç"; + +/* No comment provided by engineer. */ +"Open chat" = "Sohbeti aç"; + +/* authentication reason */ +"Open chat console" = "Sohbet konsolunu aç"; + +/* No comment provided by engineer. */ +"Open group" = "Grubu aç"; + +/* No comment provided by engineer. */ +"Open Settings" = "Ayarları aç"; + +/* authentication reason */ +"Open user profiles" = "Kullanıcı profillerini aç"; + +/* No comment provided by engineer. */ +"Open-source protocol and code – anybody can run the servers." = "Açık kaynak protokolü ve kodu - herhangi biri sunucuları çalıştırabilir."; + +/* No comment provided by engineer. */ +"Opening app…" = "Uygulama açılıyor…"; + +/* No comment provided by engineer. */ +"Or scan QR code" = "Veya QR kodu okut"; + +/* No comment provided by engineer. */ +"Or show this code" = "Veya bu kodu göster"; + +/* member role */ +"owner" = "sahip"; + +/* No comment provided by engineer. */ +"Passcode" = "Şifre"; + +/* No comment provided by engineer. */ +"Passcode changed!" = "Şifre değiştirildi!"; + +/* No comment provided by engineer. */ +"Passcode entry" = "Şifre girişi"; + +/* No comment provided by engineer. */ +"Passcode not changed!" = "Şifre değiştirilmedi!"; + +/* No comment provided by engineer. */ +"Passcode set!" = "Şifre ayarlandı!"; + +/* No comment provided by engineer. */ +"Password to show" = "Gösterilecek şifre"; + +/* No comment provided by engineer. */ +"Paste desktop address" = "Bilgisayar adresini yapıştır"; + +/* No comment provided by engineer. */ +"Paste image" = "Fotoğraf yapıştır"; + +/* No comment provided by engineer. */ +"Paste the link you received" = "Aldığın bağlantıyı yapıştır"; + +/* No comment provided by engineer. */ +"peer-to-peer" = "eşler arası"; + +/* No comment provided by engineer. */ +"People can connect to you only via the links you share." = "İnsanlar size yalnızca paylaştığınız bağlantılar üzerinden ulaşabilir."; + +/* No comment provided by engineer. */ +"Periodically" = "Periyodik olarak"; + +/* message decrypt error item */ +"Permanent decryption error" = "Kalıcı şifre çözümü hatası"; + +/* No comment provided by engineer. */ +"PING count" = "PING sayısı"; + +/* No comment provided by engineer. */ +"PING interval" = "PING aralığı"; + +/* No comment provided by engineer. */ +"Please ask your contact to enable sending voice messages." = "Lütfen konuştuğunuz kişiden sesli mesaj göndermeyi etkinleştirmesini isteyin."; + +/* No comment provided by engineer. */ +"Please check that you used the correct link or ask your contact to send you another one." = "Lütfen doğru bağlantıyı kullandığınızı kontrol edin veya kişiden size başka bir bağlantı göndermesini isteyin."; + +/* No comment provided by engineer. */ +"Please check your network connection with %@ and try again." = "Lütfen ağ bağlantınızı %@ ile kontrol edin ve tekrar deneyin."; + +/* No comment provided by engineer. */ +"Please check yours and your contact preferences." = "Lütfen sizinkini ve iletişim tercihlerinizi kontrol edin."; + +/* No comment provided by engineer. */ +"Please contact developers.\nError: %@" = "Lütfen geliştiricilerle irtibata geçin.\nHata: %@"; + +/* No comment provided by engineer. */ +"Please contact group admin." = "Lütfen grup yöneticisiyle irtibata geçin."; + +/* No comment provided by engineer. */ +"Please enter correct current passphrase." = "Lütfen şu anki doğru olan parolayı girin."; + +/* No comment provided by engineer. */ +"Please enter the previous password after restoring database backup. This action can not be undone." = "Veritabanı yedeğini geri yükledikten sonra lütfen önceki şifreyi girin. Bu işlem geri alınamaz."; + +/* No comment provided by engineer. */ +"Please remember or store it securely - there is no way to recover a lost passcode!" = "Lütfen iyi hatırlayın veya güvenli bir şekilde saklayın - kaybolmuş bir parolayı kurtarmanın bir yolu yoktur!"; + +/* No comment provided by engineer. */ +"Please report it to the developers." = "Lütfen geliştiricilere bildirin."; + +/* No comment provided by engineer. */ +"Please restart the app and migrate the database to enable push notifications." = "Lütfen uygulamayı yeniden başlatın ve anlık bildirimleri etkinleştirmek için veritabanını taşıyın."; + +/* No comment provided by engineer. */ +"Please store passphrase securely, you will NOT be able to access chat if you lose it." = "Lütfen parolayı güvenli bir şekilde saklayın, kaybederseniz sohbete ERİŞEMEZSİNİZ."; + +/* No comment provided by engineer. */ +"Please store passphrase securely, you will NOT be able to change it if you lose it." = "Lütfen parolayı güvenli bir şekilde saklayın, kaybederseniz parolayı DEĞİŞTİREMEZSİNİZ."; + +/* No comment provided by engineer. */ +"Polish interface" = "Lehçe arayüz"; + +/* server test error */ +"Possibly, certificate fingerprint in server address is incorrect" = "Muhtemelen, sunucu adresindeki parmakizi sertifikası doğru değil"; + +/* No comment provided by engineer. */ +"Preserve the last message draft, with attachments." = "Son mesaj taslağını ekleriyle birlikte koru."; + +/* No comment provided by engineer. */ +"Preset server" = "Ön ayarlı sunucu"; + +/* No comment provided by engineer. */ +"Preset server address" = "Ön ayarlı sunucu adresi"; + +/* No comment provided by engineer. */ +"Preview" = "Ön izleme"; + +/* No comment provided by engineer. */ +"Privacy & security" = "Gizlilik & güvenlik"; + +/* No comment provided by engineer. */ +"Privacy redefined" = "Gizlilik yeniden tanımlandı"; + +/* No comment provided by engineer. */ +"Private filenames" = "Gizli dosya adları"; + +/* No comment provided by engineer. */ +"Profile and server connections" = "Profil ve sunucu bağlantıları"; + +/* No comment provided by engineer. */ +"Profile image" = "Profil fotoğrafı"; + +/* No comment provided by engineer. */ +"Profile name" = "Profil ismi"; + +/* No comment provided by engineer. */ +"Profile name:" = "Profil ismi:"; + +/* No comment provided by engineer. */ +"Profile password" = "Profil parolası"; + +/* No comment provided by engineer. */ +"Profile update will be sent to your contacts." = "Profil güncellemesi kişilerinize gönderilecektir."; + +/* No comment provided by engineer. */ +"Prohibit audio/video calls." = "Sesli/görüntülü aramaları yasakla."; + +/* No comment provided by engineer. */ +"Prohibit irreversible message deletion." = "Geri dönüşsüz mesaj silme işlemini yasakla."; + +/* No comment provided by engineer. */ +"Prohibit message reactions." = "Mesaj tepkisini yasakla."; + +/* No comment provided by engineer. */ +"Prohibit messages reactions." = "Mesajlarda tepkileri yasakla."; + +/* No comment provided by engineer. */ +"Prohibit sending direct messages to members." = "Geri dönülmez mesaj silme işlemini yasakla."; + +/* No comment provided by engineer. */ +"Prohibit sending disappearing messages." = "Kaybolan mesajların gönderimini yasakla."; + +/* No comment provided by engineer. */ +"Prohibit sending files and media." = "Dosyalar ve medya gönderimlerini yasakla."; + +/* No comment provided by engineer. */ +"Prohibit sending voice messages." = "Sesli mesajların gönderimini yasakla."; + +/* No comment provided by engineer. */ +"Protect app screen" = "Uygulama ekranını koru"; + +/* No comment provided by engineer. */ +"Protect your chat profiles with a password!" = "Bir parolayla birlikte sohbet profillerini koru!"; + +/* No comment provided by engineer. */ +"Protocol timeout" = "Protokol zaman aşımı"; + +/* No comment provided by engineer. */ +"Protocol timeout per KB" = "KB başına protokol zaman aşımı"; + +/* No comment provided by engineer. */ +"Push notifications" = "Anında bildirimler"; + +/* No comment provided by engineer. */ +"Rate the app" = "Uygulamayı değerlendir"; + +/* chat item menu */ +"React…" = "Tepki ver…"; + +/* No comment provided by engineer. */ +"Read" = "Oku"; + +/* No comment provided by engineer. */ +"Read more" = "Dahasını oku"; + +/* No comment provided by engineer. */ +"Read more in [User Guide](https://simplex.chat/docs/guide/app-settings.html#your-simplex-contact-address)." = "[Kullanıcı Rehberi]nde daha fazlasını okuyun(https://simplex.chat/docs/guide/app-settings.html#your-simplex-contact-address)."; + +/* No comment provided by engineer. */ +"Read more in [User Guide](https://simplex.chat/docs/guide/chat-profiles.html#incognito-mode)." = "[Kullanıcı Rehberi]nde daha fazlasını okuyun(https://simplex.chat/docs/guide/chat-profiles.html#incognito-mode)."; + +/* No comment provided by engineer. */ +"Read more in [User Guide](https://simplex.chat/docs/guide/readme.html#connect-to-friends)." = "[Kullanıcı Rehberi]nde daha fazlasını okuyun(https://simplex.chat/docs/guide/readme.html#connect-to-friends)."; + +/* No comment provided by engineer. */ +"Read more in our [GitHub repository](https://github.com/simplex-chat/simplex-chat#readme)." = "[GitHub deposu]nda daha fazlasını okuyun(https://github.com/simplex-chat/simplex-chat#readme)."; + +/* No comment provided by engineer. */ +"Read more in our GitHub repository." = "Daha fazlasını GitHub depomuzdan oku."; + +/* No comment provided by engineer. */ +"Receipts are disabled" = "Görüldü devre dışı bırakıldı"; + +/* No comment provided by engineer. */ +"received answer…" = "alınan cevap…"; + +/* No comment provided by engineer. */ +"Received at" = "Şuradan alındı"; + +/* copied message info */ +"Received at: %@" = "Şuradan alındı: %@"; + +/* No comment provided by engineer. */ +"received confirmation…" = "onaylama alındı…"; + +/* notification */ +"Received file event" = "Dosya etkinliği alındı"; + +/* message info title */ +"Received message" = "Mesaj alındı"; + +/* No comment provided by engineer. */ +"Receiving address will be changed to a different server. Address change will complete after sender comes online." = "Alıcı adresi farklı bir sunucuya değiştirilecektir. Gönderici çevrimiçi olduktan sonra adres değişikliği tamamlanacaktır."; + +/* No comment provided by engineer. */ +"Receiving file will be stopped." = "Dosya alımı durdurulacaktır."; + +/* No comment provided by engineer. */ +"Receiving via" = "Aracılığıyla alınıyor"; + +/* No comment provided by engineer. */ +"Recipients see updates as you type them." = "Alıcılar yazdığına göre güncellemeleri görecektir."; + +/* No comment provided by engineer. */ +"Reconnect all connected servers to force message delivery. It uses additional traffic." = "Mesaj teslimini zorlamak için bağlı tüm sunucuları yeniden bağlayın. Ek trafik kullanır."; + +/* No comment provided by engineer. */ +"Reconnect servers?" = "Sunuculara yeniden bağlanılsın mı?"; + +/* No comment provided by engineer. */ +"Record updated at" = "Kayıt şu zamanda güncellendi"; + +/* copied message info */ +"Record updated at: %@" = "Kayıt şu zamanda güncellendi: %@"; + +/* No comment provided by engineer. */ +"Reduced battery usage" = "Azaltılmış pil kullanımı"; + +/* reject incoming call via notification */ +"Reject" = "Reddet"; + +/* No comment provided by engineer. */ +"Reject (sender NOT notified)" = "Reddet (göndericiye bildirim GİTMEYECEKTİR)"; + +/* No comment provided by engineer. */ +"Reject contact request" = "Bağlanma isteğini reddet"; + +/* call status */ +"rejected call" = "geri çevrilmiş çağrı"; + +/* No comment provided by engineer. */ +"Relay server is only used if necessary. Another party can observe your IP address." = "Aktarma sunucusu yalnızca gerekli olduğunda kullanılır. Başka bir taraf IP adresinizi gözlemleyebilir."; + +/* No comment provided by engineer. */ +"Relay server protects your IP address, but it can observe the duration of the call." = "Aktarıcı sunucu IP adresinizi korur, ancak aramanın süresini gözlemleyebilir."; + +/* No comment provided by engineer. */ +"Remove" = "Sil"; + +/* No comment provided by engineer. */ +"Remove member" = "Kişiyi sil"; + +/* No comment provided by engineer. */ +"Remove member?" = "Kişi silinsin mi?"; + +/* No comment provided by engineer. */ +"Remove passphrase from keychain?" = "Anahtar Zinciri'ndeki parola silinsin mi?"; + +/* No comment provided by engineer. */ +"removed" = "kaldırıldı"; + +/* rcv group event chat item */ +"removed %@" = "%@ kaldırıldı"; + +/* rcv group event chat item */ +"removed you" = "sen kaldırıldın"; + +/* No comment provided by engineer. */ +"Renegotiate" = "Yeniden müzakere"; + +/* No comment provided by engineer. */ +"Renegotiate encryption" = "Şifrelemeyi yeniden müzakere et"; + +/* No comment provided by engineer. */ +"Renegotiate encryption?" = "Şifreleme yeniden müzakere edilsin mi?"; + +/* No comment provided by engineer. */ +"Repeat connection request?" = "Bağlantı isteği tekrarlansın mı?"; + +/* No comment provided by engineer. */ +"Repeat join request?" = "Katılma isteği tekrarlansın mı?"; + +/* chat item action */ +"Reply" = "Yanıtla"; + +/* No comment provided by engineer. */ +"Required" = "Gerekli"; + +/* No comment provided by engineer. */ +"Reset" = "Sıfırla"; + +/* No comment provided by engineer. */ +"Reset colors" = "Renkleri sıfırla"; + +/* No comment provided by engineer. */ +"Reset to defaults" = "Varsayılanlara sıfırla"; + +/* No comment provided by engineer. */ +"Restart the app to create a new chat profile" = "Yeni bir sohbet profili oluşturmak için uygulamayı yeniden başlatın"; + +/* No comment provided by engineer. */ +"Restart the app to use imported chat database" = "İçe aktarılmış sohbet veritabanını kullanmak için uygulamayı yeniden başlatın"; + +/* No comment provided by engineer. */ +"Restore" = "Geri yükle"; + +/* No comment provided by engineer. */ +"Restore database backup" = "Veritabanı yedeğini geri yükle"; + +/* No comment provided by engineer. */ +"Restore database backup?" = "Veritabanı yedeği geri yüklensin mi?"; + +/* No comment provided by engineer. */ +"Restore database error" = "Veritabanını geri yüklerken hata oluştu"; + +/* No comment provided by engineer. */ +"Retry" = "Yeniden dene"; + +/* chat item action */ +"Reveal" = "Göster"; + +/* No comment provided by engineer. */ +"Revert" = "Geri al"; + +/* No comment provided by engineer. */ +"Revoke" = "İptal et"; + +/* cancel file action */ +"Revoke file" = "Dosyayı iptal et"; + +/* No comment provided by engineer. */ +"Revoke file?" = "Dosya iptal edilsin mi?"; + +/* No comment provided by engineer. */ +"Role" = "Rol"; + +/* No comment provided by engineer. */ +"Run chat" = "Sohbeti çalıştır"; + +/* chat item action */ +"Save" = "Kaydet"; + +/* No comment provided by engineer. */ +"Save (and notify contacts)" = "Kaydet (ve kişilere bildir)"; + +/* No comment provided by engineer. */ +"Save and notify contact" = "Kaydet ve kişilere bildir"; + +/* No comment provided by engineer. */ +"Save and notify group members" = "Kaydet ve grup üyelerine bildir"; + +/* No comment provided by engineer. */ +"Save and update group profile" = "Kaydet ve grup profilini güncelle"; + +/* No comment provided by engineer. */ +"Save archive" = "Arşivi kaydet"; + +/* No comment provided by engineer. */ +"Save auto-accept settings" = "Otomatik kabul et ayarlarını kaydet"; + +/* No comment provided by engineer. */ +"Save group profile" = "Grup profilini kaydet"; + +/* No comment provided by engineer. */ +"Save passphrase and open chat" = "Parolayı kaydet ve sohbeti aç"; + +/* No comment provided by engineer. */ +"Save passphrase in Keychain" = "Parolayı Anahtar Zincirinde kaydet"; + +/* No comment provided by engineer. */ +"Save preferences?" = "Tercihler kaydedilsin mi?"; + +/* No comment provided by engineer. */ +"Save profile password" = "Profil şifresini kaydet"; + +/* No comment provided by engineer. */ +"Save servers" = "Sunucuları kaydet"; + +/* No comment provided by engineer. */ +"Save servers?" = "Sunucular kaydedilsin mi?"; + +/* No comment provided by engineer. */ +"Save settings?" = "Ayarlar kaydedilsin mi?"; + +/* No comment provided by engineer. */ +"Save welcome message?" = "Hoşgeldin mesajı kaydedilsin mi?"; + +/* No comment provided by engineer. */ +"Saved WebRTC ICE servers will be removed" = "Kaydedilmiş WebRTC ICE sunucuları silinecek"; + +/* No comment provided by engineer. */ +"Scan code" = "Kod okut"; + +/* No comment provided by engineer. */ +"Scan QR code" = "QR kodu okut"; + +/* No comment provided by engineer. */ +"Scan QR code from desktop" = "Bilgisayardan QR kodu okut"; + +/* No comment provided by engineer. */ +"Scan security code from your contact's app." = "Kişinin uygulamasından güvenlik kodunu okut."; + +/* No comment provided by engineer. */ +"Scan server QR code" = "Sunucu QR kodu okut"; + +/* No comment provided by engineer. */ +"Search" = "Ara"; + +/* No comment provided by engineer. */ +"Search or paste SimpleX link" = "Ara veya SimpleX bağlantısını yapıştır"; + +/* network option */ +"sec" = "sn"; + +/* time unit */ +"seconds" = "saniye"; + +/* No comment provided by engineer. */ +"secret" = "gizli"; + +/* server test step */ +"Secure queue" = "Sırayı koru"; + +/* No comment provided by engineer. */ +"Security assessment" = "Güvenlik değerlendirmesi"; + +/* No comment provided by engineer. */ +"Security code" = "Güvenlik kodu"; + +/* chat item text */ +"security code changed" = "güvenlik kodu değiştirildi"; + +/* No comment provided by engineer. */ +"Select" = "Seç"; + +/* No comment provided by engineer. */ +"Self-destruct" = "Kendi kendini imha"; + +/* No comment provided by engineer. */ +"Self-destruct passcode" = "Kendini imha eden şifre"; + +/* No comment provided by engineer. */ +"Self-destruct passcode changed!" = "Kendini imha eden şifre değiştirildi!"; + +/* No comment provided by engineer. */ +"Self-destruct passcode enabled!" = "Kendini imha eden şifre etkinleştirildi!"; + +/* No comment provided by engineer. */ +"Send" = "Gönder"; + +/* No comment provided by engineer. */ +"Send a live message - it will update for the recipient(s) as you type it" = "Bir canlı mesaj gönder - yazışına göre kişiye(lere) kendini günceller"; + +/* No comment provided by engineer. */ +"Send delivery receipts to" = "Görüldü bilgilerini şuraya gönder"; + +/* No comment provided by engineer. */ +"send direct message" = "doğrudan mesaj gönder"; + +/* No comment provided by engineer. */ +"Send direct message" = "Doğrudan mesaj gönder"; + +/* No comment provided by engineer. */ +"Send direct message to connect" = "Bağlanmak için doğrudan mesaj gönder"; + +/* No comment provided by engineer. */ +"Send disappearing message" = "Kaybolan bir mesaj gönder"; + +/* No comment provided by engineer. */ +"Send link previews" = "Bağlantı ön gösterimleri gönder"; + +/* No comment provided by engineer. */ +"Send live message" = "Canlı mesaj gönder"; + +/* No comment provided by engineer. */ +"Send notifications" = "Bildirimler gönder"; + +/* No comment provided by engineer. */ +"Send notifications:" = "Bildirimler gönder:"; + +/* No comment provided by engineer. */ +"Send questions and ideas" = "Fikirler ve sorular gönderin"; + +/* No comment provided by engineer. */ +"Send receipts" = "Mesajlar gönder"; + +/* No comment provided by engineer. */ +"Send them from gallery or custom keyboards." = "Bunları galeriden veya özel klavyelerden gönder."; + +/* No comment provided by engineer. */ +"Sender cancelled file transfer." = "Gönderici dosya gönderimini iptal etti."; + +/* No comment provided by engineer. */ +"Sender may have deleted the connection request." = "Gönderici bağlantı isteğini silmiş olabilir."; + +/* No comment provided by engineer. */ +"Sending delivery receipts will be enabled for all contacts in all visible chat profiles." = "Görüldü bilgisi, tüm görünür sohbet profillerindeki tüm kişiler için etkinleştirilecektir."; + +/* No comment provided by engineer. */ +"Sending delivery receipts will be enabled for all contacts." = "Görüldü bilgisi bütün kişileri için etkinleştirilecektir."; + +/* No comment provided by engineer. */ +"Sending file will be stopped." = "Dosya gönderimi durdurulacaktır."; + +/* No comment provided by engineer. */ +"Sending receipts is disabled for %lld contacts" = "Görüldü bilgisi %lld kişileri için devre dışı bırakıldı"; + +/* No comment provided by engineer. */ +"Sending receipts is disabled for %lld groups" = "Görüldü bilgisi %lld grupları için devre dışı bırakıldı"; + +/* No comment provided by engineer. */ +"Sending receipts is enabled for %lld contacts" = "Görüldü bilgisi %lld kişileri için etkinleştirildi"; + +/* No comment provided by engineer. */ +"Sending receipts is enabled for %lld groups" = "Görüldü bilgisi %lld grupları için etkinleştirildi"; + +/* No comment provided by engineer. */ +"Sending via" = "Aracılığıyla gönderiliyor"; + +/* No comment provided by engineer. */ +"Sent at" = "Şuradan gönderildi"; + +/* copied message info */ +"Sent at: %@" = "Şuradan gönderildi: %@"; + +/* notification */ +"Sent file event" = "Dosya etkinliği gönderildi"; + +/* message info title */ +"Sent message" = "Mesaj gönderildi"; + +/* No comment provided by engineer. */ +"Sent messages will be deleted after set time." = "Gönderilen mesajlar ayarlanan süreden sonra silinecektir."; + +/* server test error */ +"Server requires authorization to create queues, check password" = "Sunucunun sıra oluşturması için yetki gereklidir, şifreyi kontrol edin"; + +/* server test error */ +"Server requires authorization to upload, check password" = "Sunucunun yükleme yapması için yetki gereklidir, şifreyi kontrol edin"; + +/* No comment provided by engineer. */ +"Server test failed!" = "Sunucu testinde hata oluştu!"; + +/* No comment provided by engineer. */ +"Servers" = "Sunucular"; + +/* No comment provided by engineer. */ +"Session code" = "Oturum kodu"; + +/* No comment provided by engineer. */ +"Set 1 day" = "1 günlüğüne ayarla"; + +/* No comment provided by engineer. */ +"Set contact name…" = "Kişi adı gir…"; + +/* No comment provided by engineer. */ +"Set group preferences" = "Grup tercihlerini ayarla"; + +/* No comment provided by engineer. */ +"Set it instead of system authentication." = "Sistem kimlik doğrulaması yerine ayarla."; + +/* No comment provided by engineer. */ +"Set passcode" = "Şifre ayarla"; + +/* No comment provided by engineer. */ +"Set passphrase to export" = "Dışa aktarmak için parola ayarla"; + +/* No comment provided by engineer. */ +"Set the message shown to new members!" = "Yeni üyeler için gösterilen bir mesaj ayarla!"; + +/* No comment provided by engineer. */ +"Set timeouts for proxy/VPN" = "Vekil/VPN için zaman aşımları ayarla"; + +/* No comment provided by engineer. */ +"Settings" = "Ayarlar"; + +/* chat item action */ +"Share" = "Paylaş"; + +/* No comment provided by engineer. */ +"Share 1-time link" = "Tek kullanımlık bağlantıyı paylaş"; + +/* No comment provided by engineer. */ +"Share address" = "Adresi paylaş"; + +/* No comment provided by engineer. */ +"Share address with contacts?" = "Kişilerle adres paylaşılsın mı?"; + +/* No comment provided by engineer. */ +"Share link" = "Bağlantıyı paylaş"; + +/* No comment provided by engineer. */ +"Share this 1-time invite link" = "Bu tek kullanımlık bağlantı davetini paylaş"; + +/* No comment provided by engineer. */ +"Share with contacts" = "Kişilerle paylaş"; + +/* No comment provided by engineer. */ +"Show calls in phone history" = "Telefon geçmişinde aramaları göster"; + +/* No comment provided by engineer. */ +"Show developer options" = "Geliştirici ayarlarını göster"; + +/* No comment provided by engineer. */ +"Show last messages" = "Son mesajları göster"; + +/* No comment provided by engineer. */ +"Show preview" = "Ön gösterimi göser"; + +/* No comment provided by engineer. */ +"Show:" = "Göster:"; + +/* No comment provided by engineer. */ +"SimpleX address" = "SimpleX adresi"; + +/* No comment provided by engineer. */ +"SimpleX Address" = "SimpleX Adresi"; + +/* No comment provided by engineer. */ +"SimpleX Chat security was audited by Trail of Bits." = "SimpleX Chat güvenliği Trails of Bits tarafından denetlenmiştir."; + +/* simplex link type */ +"SimpleX contact address" = "SimpleX kişi adresi"; + +/* notification */ +"SimpleX encrypted message or connection event" = "SimpleX şifrelenmiş mesaj veya bağlantı etkinliği"; + +/* simplex link type */ +"SimpleX group link" = "SimpleX grup bağlantısı"; + +/* No comment provided by engineer. */ +"SimpleX links" = "SimpleX bağlantıları"; + +/* No comment provided by engineer. */ +"SimpleX Lock" = "SimpleX Kilidi"; + +/* No comment provided by engineer. */ +"SimpleX Lock mode" = "SimpleX Kilidi modu"; + +/* No comment provided by engineer. */ +"SimpleX Lock not enabled!" = "SimpleX Kilidi etkinleştirilmedi!"; + +/* No comment provided by engineer. */ +"SimpleX Lock turned on" = "SimpleX Kilidi açıldı"; + +/* simplex link type */ +"SimpleX one-time invitation" = "SimpleX tek kullanımlık davet"; + +/* No comment provided by engineer. */ +"Simplified incognito mode" = "Basitleştirilmiş gizli mod"; + +/* No comment provided by engineer. */ +"Skip" = "Atla"; + +/* No comment provided by engineer. */ +"Skipped messages" = "Atlanmış mesajlar"; + +/* No comment provided by engineer. */ +"Small groups (max 20)" = "Küçük gruplar (en fazla 20 kişi)"; + +/* No comment provided by engineer. */ +"SMP servers" = "SMP sunucuları"; + +/* No comment provided by engineer. */ +"Some non-fatal errors occurred during import - you may see Chat console for more details." = "İçe aktarma sırasında bazı ölümcül olmayan hatalar oluştu - daha fazla ayrıntı için Sohbet konsoluna bakabilirsiniz."; + +/* notification title */ +"Somebody" = "Biri"; + +/* No comment provided by engineer. */ +"Start chat" = "Sohbeti başlat"; + +/* No comment provided by engineer. */ +"Start chat?" = "Sohbet başlatılsın mı?"; + +/* No comment provided by engineer. */ +"Start migration" = "Geçişi başlat"; + +/* No comment provided by engineer. */ +"starting…" = "başlatılıyor…"; + +/* No comment provided by engineer. */ +"Stop" = "Dur"; + +/* No comment provided by engineer. */ +"Stop chat to enable database actions" = "Veritabanı eylemlerini etkinleştirmek için sohbeti durdur"; + +/* No comment provided by engineer. */ +"Stop chat to export, import or delete chat database. You will not be able to receive and send messages while the chat is stopped." = "Sohbet veritabanını dışa aktarmak, içe aktarmak veya silmek için sohbeti durdurun. Sohbet durdurulduğunda mesaj alamaz ve gönderemezsiniz."; + +/* No comment provided by engineer. */ +"Stop chat?" = "Sohbet durdurulsun mu?"; + +/* cancel file action */ +"Stop file" = "Dosyayı durdur"; + +/* No comment provided by engineer. */ +"Stop receiving file?" = "Dosya alımı durdurulsun mu?"; + +/* No comment provided by engineer. */ +"Stop sending file?" = "Dosya gönderimi durdurulsun mu?"; + +/* No comment provided by engineer. */ +"Stop sharing" = "Paylaşmayı durdur"; + +/* No comment provided by engineer. */ +"Stop sharing address?" = "Adresi paylaşmak durdurulsun mu?"; + +/* authentication reason */ +"Stop SimpleX" = "SimpleX'i durdur"; + +/* No comment provided by engineer. */ +"strike" = "grev"; + +/* No comment provided by engineer. */ +"Submit" = "Gönder"; + +/* No comment provided by engineer. */ +"Support SimpleX Chat" = "SimpleX Chat'e destek ol"; + +/* No comment provided by engineer. */ +"System" = "Sistem"; + +/* No comment provided by engineer. */ +"System authentication" = "Sistem yetkilendirilmesi"; + +/* No comment provided by engineer. */ +"Take picture" = "Fotoğraf çek"; + +/* No comment provided by engineer. */ +"Tap button " = "Tuşa bas "; + +/* No comment provided by engineer. */ +"Tap to activate profile." = "Profili etkinleştirmek için tıkla."; + +/* No comment provided by engineer. */ +"Tap to Connect" = "Bağlanmak için Tıkla"; + +/* No comment provided by engineer. */ +"Tap to join" = "Katılmak için tıkla"; + +/* No comment provided by engineer. */ +"Tap to join incognito" = "Gizli katılmak için tıkla"; + +/* No comment provided by engineer. */ +"Tap to paste link" = "Bağlantıyı yapıştırmak için tıkla"; + +/* No comment provided by engineer. */ +"Tap to scan" = "Taramak için tıkla"; + +/* No comment provided by engineer. */ +"Tap to start a new chat" = "Yeni bir sohbet başlatmak için tıkla"; + +/* No comment provided by engineer. */ +"TCP connection timeout" = "TCP bağlantı zaman aşımı"; + +/* No comment provided by engineer. */ +"TCP_KEEPCNT" = "TCP_CNTYİTUT"; + +/* No comment provided by engineer. */ +"TCP_KEEPIDLE" = "TCP_BOŞTAKAL"; + +/* No comment provided by engineer. */ +"TCP_KEEPINTVL" = "TCP_TVLDEKAL"; + +/* server test failure */ +"Test failed at step %@." = "Test %@ adımında başarısız oldu."; + +/* No comment provided by engineer. */ +"Test server" = "Sunucuyu test et"; + +/* No comment provided by engineer. */ +"Test servers" = "Sunucuları test et"; + +/* No comment provided by engineer. */ +"Tests failed!" = "Testler başarısız oldu!"; + +/* No comment provided by engineer. */ +"Thank you for installing SimpleX Chat!" = "SimpleX Chat'i indirdiğin için teşekkürler!"; + +/* No comment provided by engineer. */ +"Thanks to the users – [contribute via Weblate](https://github.com/simplex-chat/simplex-chat/tree/stable#help-translating-simplex-chat)!" = "Kullanıcılar için teşekkürler - [Weblate aracılığıyla katkıda bulun](https://github.com/simplex-chat/simplex-chat/tree/stable#help-translating-simplex-chat)!"; + +/* No comment provided by engineer. */ +"Thanks to the users – contribute via Weblate!" = "Kullanıcılar için teşekkürler - Weblate aracılığıyla katkıda bulun!"; + +/* No comment provided by engineer. */ +"The 1st platform without any user identifiers – private by design." = "Herhangi bir kullanıcı tanımlayıcısı olmayan ilk platform - tasarım gereği gizli."; + +/* No comment provided by engineer. */ +"The app can notify you when you receive messages or contact requests - please open settings to enable." = "Uygulama, mesaj veya iletişim isteği aldığınızda sizi bilgilendirebilir - etkinleştirmek için lütfen ayarları açın."; + +/* No comment provided by engineer. */ +"The attempt to change database passphrase was not completed." = "Veritabanı parolasını değiştirme girişimi tamamlanmadı."; + +/* No comment provided by engineer. */ +"The code you scanned is not a SimpleX link QR code." = "Taradığınız kod bir SimpleX bağlantı QR kodu değildir."; + +/* No comment provided by engineer. */ +"The connection you accepted will be cancelled!" = "Bağlantı kabulünüz iptal edilecektir!"; + +/* No comment provided by engineer. */ +"The contact you shared this link with will NOT be able to connect!" = "Bu bağlantıyı paylaştığınız kişi BAĞLANAMAYACAKTIR!"; + +/* No comment provided by engineer. */ +"The created archive is available via app Settings / Database / Old database archive." = "Oluşturulan arşive uygulama üzerinden Ayarlar / Veritabanı / Eski veritabanı arşivi üzerinden erişilebilir."; + +/* No comment provided by engineer. */ +"The encryption is working and the new encryption agreement is not required. It may result in connection errors!" = "Şifreleme çalışıyor ve yeni şifreleme anlaşması gerekli değil. Bağlantı hatalarına neden olabilir!"; + +/* No comment provided by engineer. */ +"The hash of the previous message is different." = "Önceki mesajın hash'i farklı."; + +/* No comment provided by engineer. */ +"The ID of the next message is incorrect (less or equal to the previous).\nIt can happen because of some bug or when the connection is compromised." = "Bir sonraki mesajın kimliği yanlış (bir öncekinden az veya aynı).\nBazı hatalar nedeniyle veya bağlantı tehlikeye girdiğinde meydana gelebilir."; + +/* No comment provided by engineer. */ +"The message will be deleted for all members." = "Mesaj tüm üyeler için silinecektir."; + +/* No comment provided by engineer. */ +"The message will be marked as moderated for all members." = "Mesaj tüm üyeler için yönetilmiş olarak işaretlenecektir."; + +/* No comment provided by engineer. */ +"The next generation of private messaging" = "Gizli mesajlaşmanın yeni nesli"; + +/* No comment provided by engineer. */ +"The old database was not removed during the migration, it can be deleted." = "Eski veritabanı geçiş sırasında kaldırılmadı, silinebilir."; + +/* No comment provided by engineer. */ +"The profile is only shared with your contacts." = "Profil sadece kişilerinle paylaşılacak."; + +/* No comment provided by engineer. */ +"The second tick we missed! ✅" = "Özlediğimiz ikinci tik! ✅"; + +/* No comment provided by engineer. */ +"The sender will NOT be notified" = "Gönderene BİLDİRİLMEYECEKTİR"; + +/* No comment provided by engineer. */ +"The servers for new connections of your current chat profile **%@**." = "Mevcut sohbet profilinizin yeni bağlantıları için sunucular **%@**."; + +/* No comment provided by engineer. */ +"The text you pasted is not a SimpleX link." = "Yapıştırdığın metin bir SimpleX bağlantısı değildir."; + +/* No comment provided by engineer. */ +"Theme" = "Tema"; + +/* No comment provided by engineer. */ +"These settings are for your current profile **%@**." = "Bu ayarlar mevcut profiliniz **%@** içindir."; + +/* No comment provided by engineer. */ +"They can be overridden in contact and group settings." = "Bunlar kişi ve grup ayarlarında geçersiz kılınabilir."; + +/* No comment provided by engineer. */ +"This action cannot be undone - all received and sent files and media will be deleted. Low resolution pictures will remain." = "Bu işlem geri alınamaz - alınan ve gönderilen tüm dosyalar ve medya silinecektir. Düşük çözünürlüklü resimler kalacaktır."; + +/* No comment provided by engineer. */ +"This action cannot be undone - the messages sent and received earlier than selected will be deleted. It may take several minutes." = "Bu işlem geri alınamaz - seçilenden daha önce gönderilen ve alınan mesajlar silinecektir. Bu işlem birkaç dakika sürebilir."; + +/* No comment provided by engineer. */ +"This action cannot be undone - your profile, contacts, messages and files will be irreversibly lost." = "Bu işlem geri alınamaz - profiliniz, kişileriniz, mesajlarınız ve dosyalarınız geri döndürülemez şekilde kaybolacaktır."; + +/* notification title */ +"this contact" = "Bu kişi"; + +/* No comment provided by engineer. */ +"This device name" = "Bu cihazın ismi"; + +/* No comment provided by engineer. */ +"This group has over %lld members, delivery receipts are not sent." = "Bu grubun %lld den fazla üyesi var,görüldü bilgisi gönderilmedi."; + +/* No comment provided by engineer. */ +"This group no longer exists." = "Bu grup artık mevcut değildir."; + +/* No comment provided by engineer. */ +"This is your own one-time link!" = "Bu senin kendi tek kullanımlık bağlantın!"; + +/* No comment provided by engineer. */ +"This is your own SimpleX address!" = "Bu senin kendi SimpleX adresin!"; + +/* No comment provided by engineer. */ +"This setting applies to messages in your current chat profile **%@**." = "Bu ayar, geçerli sohbet profiliniz **%@** deki mesajlara uygulanır."; + +/* No comment provided by engineer. */ +"To ask any questions and to receive updates:" = "Soru sormak ve güncellemeleri almak için:"; + +/* No comment provided by engineer. */ +"To connect, your contact can scan QR code or use the link in the app." = "Bağlanmak için, kişi QR kodu okutabilir veya uygulama içinden bağlantıyı kullanabilir."; + +/* No comment provided by engineer. */ +"To hide unwanted messages." = "İstenmeyen mesajları gizlemek için."; + +/* No comment provided by engineer. */ +"To make a new connection" = "Yeni bir bağlantı oluşturmak için"; + +/* No comment provided by engineer. */ +"To protect privacy, instead of user IDs used by all other platforms, SimpleX has identifiers for message queues, separate for each of your contacts." = "Gizliliği korumak için, diğer tüm platformlar gibi kullanıcı kimliği kullanmak yerine, SimpleX mesaj kuyrukları için kişilerinizin her biri için ayrı tanımlayıcılara sahiptir."; + +/* No comment provided by engineer. */ +"To protect timezone, image/voice files use UTC." = "Zaman bölgesini korumak için,fotoğraf/ses dosyaları UTC kullanır."; + +/* No comment provided by engineer. */ +"To protect your information, turn on SimpleX Lock.\nYou will be prompted to complete authentication before this feature is enabled." = "Bilgilerinizi korumak için SimpleX Lock özelliğini açın.\nBu özellik etkinleştirilmeden önce kimlik doğrulamayı tamamlamanız istenecektir."; + +/* No comment provided by engineer. */ +"To record voice message please grant permission to use Microphone." = "Sesli mesaj kaydetmek için lütfen Mikrofon kullanım izni verin."; + +/* No comment provided by engineer. */ +"To reveal your hidden profile, enter a full password into a search field in **Your chat profiles** page." = "Gizli profilinizi ortaya çıkarmak için **Sohbet profilleriniz** sayfasındaki arama alanına tam bir şifre girin."; + +/* No comment provided by engineer. */ +"To support instant push notifications the chat database has to be migrated." = "Anlık anlık bildirimleri desteklemek için sohbet veritabanının taşınması gerekir."; + +/* No comment provided by engineer. */ +"To verify end-to-end encryption with your contact compare (or scan) the code on your devices." = "Kişinizle uçtan uca şifrelemeyi doğrulamak için cihazlarınızdaki kodu karşılaştırın (veya tarayın)."; + +/* No comment provided by engineer. */ +"Toggle incognito when connecting." = "Bağlanırken gizli moda geçiş yap."; + +/* No comment provided by engineer. */ +"Transport isolation" = "Taşıma izolasyonu"; + +/* No comment provided by engineer. */ +"Trying to connect to the server used to receive messages from this contact (error: %@)." = "Bu kişiden mesaj almak için kullanılan sunucuya bağlanılmaya çalışılıyor (hata: %@)."; + +/* No comment provided by engineer. */ +"Trying to connect to the server used to receive messages from this contact." = "Bu kişiden mesaj almak için kullanılan sunucuya bağlanılmaya çalışılıyor."; + +/* No comment provided by engineer. */ +"Turn off" = "Kapat"; + +/* No comment provided by engineer. */ +"Turn on" = "Aç"; + +/* No comment provided by engineer. */ +"Unable to record voice message" = "Sesli mesaj kaydedilemedi"; + +/* No comment provided by engineer. */ +"Unblock" = "Engeli kaldır"; + +/* No comment provided by engineer. */ +"Unblock member" = "Üyenin engelini kaldır"; + +/* No comment provided by engineer. */ +"Unblock member?" = "Üyenin engeli kaldırılsın mı?"; + +/* item status description */ +"Unexpected error: %@" = "Beklenmeyen hata: %@"; + +/* No comment provided by engineer. */ +"Unexpected migration state" = "Beklenmeyen geçiş durumu"; + +/* No comment provided by engineer. */ +"Unfav." = "Favorilerden çık."; + +/* No comment provided by engineer. */ +"Unhide" = "Gizlemeyi kaldır"; + +/* No comment provided by engineer. */ +"Unhide chat profile" = "Sohbet profilinin gizlemesini kaldır"; + +/* No comment provided by engineer. */ +"Unhide profile" = "Proflin gizlenmesini kaldır"; + +/* No comment provided by engineer. */ +"Unit" = "Birim"; + +/* connection info */ +"unknown" = "bilinmeyen"; + +/* callkit banner */ +"Unknown caller" = "Bilinmeyen arayan"; + +/* No comment provided by engineer. */ +"Unknown database error: %@" = "Bilinmeyen veritabanı hatası: %@"; + +/* No comment provided by engineer. */ +"Unknown error" = "Bilinmeyen hata"; + +/* No comment provided by engineer. */ +"Unless you use iOS call interface, enable Do Not Disturb mode to avoid interruptions." = "iOS arama arayüzünü kullanmadığınız sürece, kesintileri önlemek için Rahatsız Etmeyin modunu etkinleştirin."; + +/* No comment provided by engineer. */ +"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." = "Kişiniz bağlantıyı silmediyse veya bu bağlantı kullanılmadıysa, bu bir hata olabilir - lütfen bildirin.\nBağlanmak için lütfen kişinizden başka bir bağlantı oluşturmasını isteyin ve sabit bir ağ bağlantınız olduğunu kontrol edin."; + +/* No comment provided by engineer. */ +"Unlink" = "Bağlantıyı Kaldır"; + +/* No comment provided by engineer. */ +"Unlink desktop?" = "Bilgisayarla bağlantı kaldırılsın mı?"; + +/* No comment provided by engineer. */ +"Unlock" = "Kilidi aç"; + +/* authentication reason */ +"Unlock app" = "Uygulama kilidini aç"; + +/* No comment provided by engineer. */ +"Unmute" = "Susturmayı kaldır"; + +/* No comment provided by engineer. */ +"Unread" = "Okunmamış"; + +/* No comment provided by engineer. */ +"Update" = "Güncelle"; + +/* No comment provided by engineer. */ +"Update .onion hosts setting?" = ".onion ana bilgisayarların ayarı güncellensin mi?"; + +/* No comment provided by engineer. */ +"Update database passphrase" = "Veritabanı parolasını güncelle"; + +/* No comment provided by engineer. */ +"Update network settings?" = "Bağlantı ayarları güncellensin mi?"; + +/* No comment provided by engineer. */ +"Update transport isolation mode?" = "Taşıma izolasyon modu güncellensin mi?"; + +/* rcv group event chat item */ +"updated group profile" = "grup profili güncellendi"; + +/* No comment provided by engineer. */ +"Updating settings will re-connect the client to all servers." = "Ayarların güncellenmesi, istemciyi tüm sunuculara yeniden bağlayacaktır."; + +/* No comment provided by engineer. */ +"Updating this setting will re-connect the client to all servers." = "Bu ayarın güncellenmesi, istemciyi tüm sunuculara yeniden bağlayacaktır."; + +/* No comment provided by engineer. */ +"Upgrade and open chat" = "Yükselt ve sohbeti aç"; + +/* server test step */ +"Upload file" = "Dosya yükle"; + +/* No comment provided by engineer. */ +"Use .onion hosts" = ".onion ana bilgisayarlarını kullan"; + +/* No comment provided by engineer. */ +"Use chat" = "Sohbeti kullan"; + +/* No comment provided by engineer. */ +"Use current profile" = "Şu anki profili kullan"; + +/* No comment provided by engineer. */ +"Use for new connections" = "Yeni bağlantılar için kullan"; + +/* No comment provided by engineer. */ +"Use from desktop" = "Bilgisayardan kullan"; + +/* No comment provided by engineer. */ +"Use iOS call interface" = "iOS arama arayüzünden kullan"; + +/* No comment provided by engineer. */ +"Use new incognito profile" = "Yeni gizli profilden kullan"; + +/* No comment provided by engineer. */ +"Use only local notifications?" = "Sadece yerel bildirimler kullanılsın mı?"; + +/* No comment provided by engineer. */ +"Use server" = "Sunucu kullan"; + +/* No comment provided by engineer. */ +"Use SimpleX Chat servers?" = "SimpleX Chat sunucuları kullanılsın mı?"; + +/* No comment provided by engineer. */ +"User profile" = "Kullanıcı profili"; + +/* No comment provided by engineer. */ +"Using .onion hosts requires compatible VPN provider." = ".onion ana bilgisayarlarını kullanmak için uyumlu VPN sağlayıcısı gerekir."; + +/* No comment provided by engineer. */ +"Using SimpleX Chat servers." = "SimpleX Chat sunucuları kullanılıyor."; + +/* No comment provided by engineer. */ +"v%@" = "v%@"; + +/* No comment provided by engineer. */ +"v%@ (%@)" = "v%@ (%@)"; + +/* No comment provided by engineer. */ +"Verify code with desktop" = "Bilgisayarla kodu doğrula"; + +/* No comment provided by engineer. */ +"Verify connection" = "Bağlantıyı doğrula"; + +/* No comment provided by engineer. */ +"Verify connection security" = "Bağlantı güvenliğini doğrula"; + +/* No comment provided by engineer. */ +"Verify connections" = "Bağlantıları doğrula"; + +/* No comment provided by engineer. */ +"Verify security code" = "Güvenlik kodunu doğrula"; + +/* No comment provided by engineer. */ +"Via browser" = "Tarayıcı üzerinden"; + +/* chat list item description */ +"via contact address link" = "bağlantı adres uzantısı ile"; + +/* chat list item description */ +"via group link" = "grup bağlantısı ile"; + +/* chat list item description */ +"via one-time link" = "tek kullanımlık bağlantısı ile"; + +/* No comment provided by engineer. */ +"via relay" = "yönlendirici aracılığıyla"; + +/* No comment provided by engineer. */ +"Via secure quantum resistant protocol." = "Güvenli kuantum dirençli protokol ile."; + +/* No comment provided by engineer. */ +"Video call" = "Görüntülü arama"; + +/* No comment provided by engineer. */ +"video call (not e2e encrypted)" = "Görüntülü arama (şifrelenmiş değil)"; + +/* No comment provided by engineer. */ +"Video will be received when your contact completes uploading it." = "Kişiniz yüklemeyi tamamladığında video alınacaktır."; + +/* No comment provided by engineer. */ +"Video will be received when your contact is online, please wait or check later!" = "Kişiniz çevrimiçi olduğunda video alınacaktır, lütfen bekleyin veya daha sonra kontrol edin!"; + +/* No comment provided by engineer. */ +"Videos and files up to 1gb" = "1gb'a kadar videolar ve dosyalar"; + +/* No comment provided by engineer. */ +"View security code" = "Güvenlik kodunu görüntüle"; + +/* No comment provided by engineer. */ +"Voice message…" = "Sesli mesaj…"; + +/* chat feature */ +"Voice messages" = "Sesli mesajlar"; + +/* No comment provided by engineer. */ +"Voice messages are prohibited in this chat." = "Bu sohbette sesli mesajlar yasaktır."; + +/* No comment provided by engineer. */ +"Voice messages are prohibited in this group." = "Bu grupta sesli mesajlar yasaktır."; + +/* No comment provided by engineer. */ +"Voice messages prohibited!" = "Sesli mesajlar yasaktır!"; + +/* No comment provided by engineer. */ +"waiting for answer…" = "cevap bekleniyor…"; + +/* No comment provided by engineer. */ +"waiting for confirmation…" = "onay bekleniyor…"; + +/* No comment provided by engineer. */ +"Waiting for desktop..." = "Bilgisayar için bekleniyor..."; + +/* No comment provided by engineer. */ +"Waiting for file" = "Dosya bekleniyor"; + +/* No comment provided by engineer. */ +"Waiting for image" = "Görsel bekleniyor"; + +/* No comment provided by engineer. */ +"Waiting for video" = "Video bekleniyor"; + +/* No comment provided by engineer. */ +"wants to connect to you!" = "bağlanmak istiyor!"; + +/* No comment provided by engineer. */ +"Warning: you may lose some data!" = "Uyarı: Bazı verileri kaybedebilirsin!"; + +/* No comment provided by engineer. */ +"WebRTC ICE servers" = "WebRTC ICE sunucuları"; + +/* time unit */ +"weeks" = "haftalar"; + +/* No comment provided by engineer. */ +"Welcome %@!" = "Hoşgeldin %@!"; + +/* No comment provided by engineer. */ +"Welcome message" = "Karşılama mesajı"; + +/* No comment provided by engineer. */ +"What's new" = "Neler yeni"; + +/* No comment provided by engineer. */ +"When available" = "Mevcut olduğunda"; + +/* No comment provided by engineer. */ +"When people request to connect, you can accept or reject it." = "İnsanlar bağlantı talebinde bulunduğunda, kabul edebilir veya reddedebilirsiniz."; + +/* No comment provided by engineer. */ +"When you share an incognito profile with somebody, this profile will be used for the groups they invite you to." = "Biriyle gizli bir profil paylaştığınızda, bu profil sizi davet ettikleri gruplar için kullanılacaktır."; + +/* No comment provided by engineer. */ +"With optional welcome message." = "İsteğe bağlı karşılama mesajı ile."; + +/* No comment provided by engineer. */ +"Wrong database passphrase" = "Yanlış veritabanı parolası"; + +/* No comment provided by engineer. */ +"Wrong passphrase!" = "Yanlış parola!"; + +/* No comment provided by engineer. */ +"XFTP servers" = "XFTP sunucuları"; + +/* pref value */ +"yes" = "evet"; + +/* No comment provided by engineer. */ +"You" = "Sen"; + +/* No comment provided by engineer. */ +"You accepted connection" = "Bağlantıyı onayladın"; + +/* No comment provided by engineer. */ +"You allow" = "İzin veriyorsunuz"; + +/* No comment provided by engineer. */ +"You already have a chat profile with the same display name. Please choose another name." = "Aynı görünen ada sahip bir konuşma profilin zaten var. Lütfen başka bir ad seç."; + +/* No comment provided by engineer. */ +"You are already connected to %@." = "Zaten %@'a bağlısınız."; + +/* No comment provided by engineer. */ +"You are already connecting to %@." = "Zaten %@'a bağlanıyorsunuz."; + +/* No comment provided by engineer. */ +"You are already connecting via this one-time link!" = "Bu tek seferlik bağlantı üzerinden zaten bağlanıyorsunuz!"; + +/* No comment provided by engineer. */ +"You are already in group %@." = "Zaten %@ grubundasın."; + +/* No comment provided by engineer. */ +"You are already joining the group %@." = "Zaten %@ grubuna katılıyorsunuz."; + +/* No comment provided by engineer. */ +"You are already joining the group via this link!" = "Bu bağlantı üzerinden gruba zaten katılıyorsunuz!"; + +/* No comment provided by engineer. */ +"You are already joining the group via this link." = "Gruba zaten bu bağlantı üzerinden katılıyorsunuz."; + +/* No comment provided by engineer. */ +"You are already joining the group!\nRepeat join request?" = "Gruba zaten katılıyorsunuz!\nKatılma isteği tekrarlansın mı?"; + +/* No comment provided by engineer. */ +"You are connected to the server used to receive messages from this contact." = "Bu kişiden mesaj almak için kullanılan sunucuya bağlısınız."; + +/* No comment provided by engineer. */ +"you are invited to group" = "gruba davet edildiniz"; + +/* No comment provided by engineer. */ +"You are invited to group" = "Gruba davet edildiniz"; + +/* No comment provided by engineer. */ +"you are observer" = "gözlemcisiniz"; + +/* No comment provided by engineer. */ +"You can accept calls from lock screen, without device and app authentication." = "Cihaz ve uygulama kimlik doğrulaması olmadan kilit ekranından çağrı kabul edebilirsiniz."; + +/* No comment provided by engineer. */ +"You can create it later" = "Daha sonra oluşturabilirsiniz"; + +/* No comment provided by engineer. */ +"You can enable later via Settings" = "Daha sonra Ayarlardan etkinleştirebilirsin"; + +/* No comment provided by engineer. */ +"You can enable them later via app Privacy & Security settings." = "Daha sonra uygulamanın Gizlilik ve Güvenlik ayarlarından etkinleştirebilirsiniz."; + +/* No comment provided by engineer. */ +"You can hide or mute a user profile - swipe it to the right." = "Bir kullanıcı profilini gizleyebilir veya sessize alabilirsiniz - sağa kaydırın."; + +/* No comment provided by engineer. */ +"You can make it visible to your SimpleX contacts via Settings." = "Ayarlardan SimpleX kişilerinize görünür yapabilirsiniz."; + +/* notification body */ +"You can now send messages to %@" = "Artık %@ adresine mesaj gönderebilirsin"; + +/* No comment provided by engineer. */ +"You can set lock screen notification preview via settings." = "Kilit ekranı bildirim önizlemesini ayarlar üzerinden ayarlayabilirsiniz."; + +/* No comment provided by engineer. */ +"You can share a link or a QR code - anybody will be able to join the group. You won't lose members of the group if you later delete it." = "Bir bağlantı veya QR kodu paylaşabilirsiniz - bu durumda herkes gruba katılabilir. Daha sonra silseniz bile grubun üyelerini kaybetmezsiniz."; + +/* No comment provided by engineer. */ +"You can share this address with your contacts to let them connect with **%@**." = "Bu adresi kişilerinizle paylaşarak onların **%@** ile bağlantı kurmasını sağlayabilirsiniz."; + +/* No comment provided by engineer. */ +"You can share your address as a link or QR code - anybody can connect to you." = "Adresinizi bir bağlantı veya QR kodu olarak paylaşabilirsiniz - herkes size bağlanabilir."; + +/* No comment provided by engineer. */ +"You can start chat via app Settings / Database or by restarting the app" = "Sohbeti uygulamada Ayarlar / Veritabanı üzerinden veya uygulamayı yeniden başlatarak başlatabilirsiniz"; + +/* No comment provided by engineer. */ +"You can turn on SimpleX Lock via Settings." = "SimpleX Kilidini Ayarlar üzerinden açabilirsiniz."; + +/* No comment provided by engineer. */ +"You can use markdown to format messages:" = "Mesajları biçimlendirmek için markdown kullanabilirsiniz:"; + +/* No comment provided by engineer. */ +"You can view invitation link again in connection details." = "Bağlantı detaylarından davet bağlantısını yeniden görüntüleyebilirsin."; + +/* No comment provided by engineer. */ +"You can't send messages!" = "Mesajlar gönderemezsiniz!"; + +/* chat item text */ +"you changed address" = "adresinizi değiştirdiniz"; + +/* chat item text */ +"you changed address for %@" = "adresinizi %@ ile değiştirdiniz"; + +/* snd group event chat item */ +"you changed role for yourself to %@" = "kişisel yetkinizi %@ olarak değiştirdiniz"; + +/* snd group event chat item */ +"you changed role of %@ to %@" = "%1$@'in yetkisini %2$@ olarak değiştirdiniz"; + +/* No comment provided by engineer. */ +"You control through which server(s) **to receive** the messages, your contacts – the servers you use to message them." = "Mesajların hangi sunucu(lar)dan **alınacağını**, kişilerinizi - onlara mesaj göndermek için kullandığınız sunucuları - siz kontrol edersiniz."; + +/* No comment provided by engineer. */ +"You could not be verified; please try again." = "Doğrulanamadınız; lütfen tekrar deneyin."; + +/* No comment provided by engineer. */ +"You have already requested connection via this address!" = "Bu adres üzerinden zaten bağlantı talebinde bulundunuz!"; + +/* No comment provided by engineer. */ +"You have already requested connection!\nRepeat connection request?" = "Zaten bağlantı isteğinde bulundunuz!\nBağlantı isteği tekrarlansın mı?"; + +/* No comment provided by engineer. */ +"You have no chats" = "Hiç sohbetiniz yok"; + +/* No comment provided by engineer. */ +"You have to enter passphrase every time the app starts - it is not stored on the device." = "Uygulama her başladığında parola girmeniz gerekir - parola cihazınızda saklanmaz."; + +/* No comment provided by engineer. */ +"You invited a contact" = "Bir kişiyi davet ettin"; + +/* No comment provided by engineer. */ +"You joined this group" = "Bu gruba katıldınız"; + +/* No comment provided by engineer. */ +"You joined this group. Connecting to inviting group member." = "Bu gruba katıldınız. Davet eden grup üyesine bağlanılıyor."; + +/* snd group event chat item */ +"you left" = "terk ettiniz"; + +/* No comment provided by engineer. */ +"You must use the most recent version of your chat database on one device ONLY, otherwise you may stop receiving the messages from some contacts." = "Sohbet veritabanınızın en son sürümünü SADECE bir cihazda kullanmalısınız, aksi takdirde bazı kişilerden daha fazla mesaj alamayabilirsiniz."; + +/* No comment provided by engineer. */ +"You need to allow your contact to send voice messages to be able to send them." = "Sesli mesaj gönderebilmeniz için kişinizin de sesli mesaj göndermesine izin vermeniz gerekir."; + +/* No comment provided by engineer. */ +"You rejected group invitation" = "Grup davetini reddettiniz."; + +/* snd group event chat item */ +"you removed %@" = "%@'yi çıkarttınız"; + +/* No comment provided by engineer. */ +"You sent group invitation" = "Grup daveti gönderdiniz"; + +/* chat list item description */ +"you shared one-time link" = "tek kullanımlık bağlantınızı paylaştınız"; + +/* chat list item description */ +"you shared one-time link incognito" = "tek kullanımlık link paylaştınız gizli"; + +/* No comment provided by engineer. */ +"You will be connected to group when the group host's device is online, please wait or check later!" = "Grup sahibinin cihazı çevrimiçi olduğunda gruba bağlanacaksınız, lütfen bekleyin veya daha sonra kontrol edin!"; + +/* No comment provided by engineer. */ +"You will be connected when group link host's device is online, please wait or check later!" = "Grup sahibinin cihazı çevrimiçi olduğunda gruba bağlanacaksınız, lütfen bekleyin veya daha sonra kontrol edin!"; + +/* No comment provided by engineer. */ +"You will be connected when your connection request is accepted, please wait or check later!" = "Bağlantı isteğiniz kabul edildiğinde bağlanacaksınız, lütfen bekleyin veya daha sonra kontrol edin!"; + +/* No comment provided by engineer. */ +"You will be connected when your contact's device is online, please wait or check later!" = "Kişinizin cihazı çevrimiçi olduğunda bağlanacaksınız, lütfen bekleyin veya daha sonra kontrol edin!"; + +/* No comment provided by engineer. */ +"You will be required to authenticate when you start or resume the app after 30 seconds in background." = "Arka planda 30 saniye kaldıktan sonra uygulamayı başlattığınızda veya devam ettirdiğinizde kimlik doğrulaması yapmanız gerekecektir."; + +/* No comment provided by engineer. */ +"You will connect to all group members." = "Bütün grup üyelerine bağlanacaksın."; + +/* No comment provided by engineer. */ +"You will still receive calls and notifications from muted profiles when they are active." = "Aktif olduklarında sessize alınmış profillerden arama ve bildirim almaya devam edersiniz."; + +/* No comment provided by engineer. */ +"You will stop receiving messages from this group. Chat history will be preserved." = "Bu gruptan artık mesaj almayacaksınız. Sohbet geçmişi korunacaktır."; + +/* No comment provided by engineer. */ +"You won't lose your contacts if you later delete your address." = "Eğer sonradan bağlantınızı silseniz bile kişilerinizi kaybetmeyeceksiniz."; + +/* No comment provided by engineer. */ +"you: " = "sen: "; + +/* No comment provided by engineer. */ +"You're trying to invite contact with whom you've shared an incognito profile to the group in which you're using your main profile" = "Gizli bir profil paylaştığınız kişiyi ana profilinizi kullandığınız gruba davet etmeye çalışıyorsunuz"; + +/* No comment provided by engineer. */ +"You're using an incognito profile for this group - to prevent sharing your main profile inviting contacts is not allowed" = "Bu grup için gizli bir profil kullanıyorsunuz - ana profilinizi paylaşmayı önlemek için kişileri davet etmeye izin verilmiyor"; + +/* No comment provided by engineer. */ +"Your %@ servers" = "%@ sunucularınız"; + +/* No comment provided by engineer. */ +"Your calls" = "Aramaların"; + +/* No comment provided by engineer. */ +"Your chat database" = "Sohbet veritabanınız"; + +/* No comment provided by engineer. */ +"Your chat database is not encrypted - set passphrase to encrypt it." = "Sohbet veritabanınız şifrelenmemiş - şifrelemek için parola ayarlayın."; + +/* No comment provided by engineer. */ +"Your chat profiles" = "Sohbet profillerin"; + +/* No comment provided by engineer. */ +"Your contact needs to be online for the connection to complete.\nYou can cancel this connection and remove the contact (and try later with a new link)." = "Bağlantının tamamlanması için kişinizin çevrimiçi olması gerekir.\nBu bağlantıyı iptal edebilir ve kişiyi kaldırabilirsiniz (ve daha sonra yeni bir bağlantıyla deneyebilirsiniz)."; + +/* No comment provided by engineer. */ +"Your contact sent a file that is larger than currently supported maximum size (%@)." = "Kişiniz şu anda desteklenen maksimum boyuttan (%@) daha büyük bir dosya gönderdi."; + +/* No comment provided by engineer. */ +"Your contacts can allow full message deletion." = "Kişileriniz tam mesaj silme işlemine izin verebilir."; + +/* No comment provided by engineer. */ +"Your contacts will remain connected." = "Kişileriniz bağlı kalacaktır."; + +/* No comment provided by engineer. */ +"Your current chat database will be DELETED and REPLACED with the imported one." = "Mevcut sohbet veritabanınız SİLİNECEK ve içe aktarılan veritabanıyla DEĞİŞTİRİLECEKTİR."; + +/* No comment provided by engineer. */ +"Your current profile" = "Mevcut profiliniz"; + +/* No comment provided by engineer. */ +"Your ICE servers" = "ICE sunucularınız"; + +/* No comment provided by engineer. */ +"Your preferences" = "Tercihleriniz"; + +/* No comment provided by engineer. */ +"Your privacy" = "Gizliliğiniz"; + +/* No comment provided by engineer. */ +"Your profile" = "Profiliniz"; + +/* No comment provided by engineer. */ +"Your profile **%@** will be shared." = "Profiliniz **%@** paylaşılacaktır."; + +/* No comment provided by engineer. */ +"Your profile is stored on your device and shared only with your contacts.\nSimpleX servers cannot see your profile." = "Profiliniz cihazınızda saklanır ve sadece kişilerinizle paylaşılır.\nSimpleX sunucuları profilinizi göremez."; + +/* No comment provided by engineer. */ +"Your profile, contacts and delivered messages are stored on your device." = "Profiliniz, kişileriniz ve gönderilmiş mesajlar cihazınızda saklanır."; + +/* No comment provided by engineer. */ +"Your random profile" = "Rasgele profiliniz"; + +/* No comment provided by engineer. */ +"Your server" = "Sunucunuz"; + +/* No comment provided by engineer. */ +"Your server address" = "Sunucu adresiniz"; + +/* No comment provided by engineer. */ +"Your settings" = "Ayarlarınız"; + +/* No comment provided by engineer. */ +"Your SimpleX address" = "SimpleX adresin"; + +/* No comment provided by engineer. */ +"Your SMP servers" = "SMP sunucularınız"; + +/* No comment provided by engineer. */ +"Your XFTP servers" = "XFTP sunucularınız"; + diff --git a/apps/ios/tr.lproj/SimpleX--iOS--InfoPlist.strings b/apps/ios/tr.lproj/SimpleX--iOS--InfoPlist.strings new file mode 100644 index 0000000000..fe0af4cc90 --- /dev/null +++ b/apps/ios/tr.lproj/SimpleX--iOS--InfoPlist.strings @@ -0,0 +1,18 @@ +/* Bundle name */ +"CFBundleName" = "SimpleX"; + +/* Privacy - Camera Usage Description */ +"NSCameraUsageDescription" = "SimpleX, diğer kullanıcılara bağlanmak amacıyla QR kodlarını taramak ve görüntülü aramalar için kamera erişimine ihtiyaç duyar."; + +/* Privacy - Face ID Usage Description */ +"NSFaceIDUsageDescription" = "SimpleX yerel kimlik doğrulama için Face ID kullanır"; + +/* Privacy - Local Network Usage Description */ +"NSLocalNetworkUsageDescription" = "SimpleX, aynı ağdaki masaüstü uygulaması aracılığıyla kullanıcı sohbet profilinin kullanılmasına izin vermek için yerel ağ erişimini kullanır."; + +/* Privacy - Microphone Usage Description */ +"NSMicrophoneUsageDescription" = "SimpleX'in sesli ve görüntülü aramalar ve sesli mesajları kaydetmek için mikrofon erişimine ihtiyacı vardır."; + +/* Privacy - Photo Library Additions Usage Description */ +"NSPhotoLibraryAddUsageDescription" = "SimpleX'in çekilen ve alınan medyayı kaydetmek için Fotoğraf Kitaplığı'na erişmesi gerekir"; + diff --git a/apps/ios/uk.lproj/Localizable.strings b/apps/ios/uk.lproj/Localizable.strings index aabd1a7101..be912d785d 100644 --- a/apps/ios/uk.lproj/Localizable.strings +++ b/apps/ios/uk.lproj/Localizable.strings @@ -19,9 +19,15 @@ /* No comment provided by engineer. */ "_italic_" = "\\_курсив_"; +/* No comment provided by engineer. */ +"- connect to [directory service](simplex:/contact#/?v=1-4&smp=smp%3A%2F%2Fu2dS9sG8nMNURyZwqASV4yROM28Er0luVTx5X1CsMrU%3D%40smp4.simplex.im%2FeXSPwqTkKyDO3px4fLf1wx3MvPdjdLW3%23%2F%3Fv%3D1-2%26dh%3DMCowBQYDK2VuAyEAaiv6MkMH44L2TcYrt_CsX3ZvM11WgbMEUn0hkIKTOho%253D%26srv%3Do5vmywmrnaxalvz6wi3zicyftgio6psuvyniis6gco6bp6ekl4cqj4id.onion) (BETA)!\n- delivery receipts (up to 20 members).\n- faster and more stable." = "- підключитися до [сервера каталогів](simplex:/contact#/?v=1-4&smp=smp%3A%2F%2Fu2dS9sG8nMNURyZwqASV4yROM28Er0luVTx5X1CsMrU%3D%40smp4.simplex.im%2FeXSPwqTkKyDO3px4fLf1wx3MvPdjdLW3%23%2F%3Fv%3D1-2%26dh%3DMCowBQYDK2VuAyEAaiv6MkMH44L2TcYrt_CsX3ZvM11WgbMEUn0hkIKTOho%253D%26srv%3Do5vmywmrnaxalvz6wi3zicyftgio6psuvyniis6gco6bp6ekl4cqj4id.onion) (БЕТА)!\n- підтвердження доставлення (до 20 учасників).\n- швидше і стабільніше."; + /* No comment provided by engineer. */ "- more stable message delivery.\n- a bit better groups.\n- and more!" = "- стабільніша доставка повідомлень.\n- трохи кращі групи.\n- і багато іншого!"; +/* No comment provided by engineer. */ +"- optionally notify deleted contacts.\n- profile names with spaces.\n- and more!" = "- опція сповіщати про видалені контакти.\n- імена профілів з пробілами.\n- та багато іншого!"; + /* No comment provided by engineer. */ "- voice messages up to 5 minutes.\n- custom time to disappear.\n- editing history." = "- голосові повідомлення до 5 хвилин.\n- користувальницький час зникнення.\n- історія редагування."; @@ -40,6 +46,12 @@ /* No comment provided by engineer. */ "(" = "("; +/* No comment provided by engineer. */ +"(new)" = "(новий)"; + +/* No comment provided by engineer. */ +"(this device v%@)" = "(цей пристрій v%@)"; + /* No comment provided by engineer. */ ")" = ")"; @@ -55,9 +67,6 @@ /* No comment provided by engineer. */ "**Add new contact**: to create your one-time QR Code for your contact." = "**Додати новий контакт**: щоб створити одноразовий QR-код або посилання для свого контакту."; -/* No comment provided by engineer. */ -"**Create link / QR code** for your contact to use." = "**Створіть посилання / QR-код** для використання вашим контактом."; - /* No comment provided by engineer. */ "**e2e encrypted** audio call" = "**e2e encrypted** аудіодзвінок"; @@ -70,18 +79,12 @@ /* No comment provided by engineer. */ "**Most private**: do not use SimpleX Chat notifications server, check messages periodically in the background (depends on how often you use the app)." = "**Найбільш приватний**: не використовуйте сервер сповіщень SimpleX Chat, періодично перевіряйте повідомлення у фоновому режимі (залежить від того, як часто ви користуєтесь додатком)."; -/* No comment provided by engineer. */ -"**Paste received link** or open it in the browser and tap **Open in mobile app**." = "**Вставте отримане посилання** або відкрийте його в браузері і натисніть **Відкрити в мобільному додатку**."; - /* No comment provided by engineer. */ "**Please note**: you will NOT be able to recover or change passphrase if you lose it." = "**Зверніть увагу: ви НЕ зможете відновити або змінити пароль, якщо втратите його."; /* No comment provided by engineer. */ "**Recommended**: device token and notifications are sent to SimpleX Chat notification server, but not the message content, size or who it is from." = "**Рекомендується**: токен пристрою та сповіщення надсилаються на сервер сповіщень SimpleX Chat, але не вміст повідомлення, його розмір або від кого воно надійшло."; -/* No comment provided by engineer. */ -"**Scan QR code**: to connect to your contact in person or via video call." = "**Відскануйте QR-код**: щоб з'єднатися з вашим контактом особисто або за допомогою відеодзвінка."; - /* No comment provided by engineer. */ "**Warning**: Instant push notifications require passphrase saved in Keychain." = "**Попередження**: Для отримання миттєвих пуш-сповіщень потрібна парольна фраза, збережена у брелоку."; @@ -115,12 +118,18 @@ /* No comment provided by engineer. */ "%@ %@" = "%@ %@"; +/* No comment provided by engineer. */ +"%@ and %@" = "%@ та %@"; + /* No comment provided by engineer. */ "%@ and %@ connected" = "%@ і %@ підключено"; /* copied message info, <sender> at <time> */ "%@ at %@:" = "%1$@ за %2$@:"; +/* No comment provided by engineer. */ +"%@ connected" = "%@ підключено"; + /* notification title */ "%@ is connected!" = "%@ підключено!"; @@ -136,6 +145,9 @@ /* notification title */ "%@ wants to connect!" = "%@ хоче підключитися!"; +/* No comment provided by engineer. */ +"%@, %@ and %lld members" = "%@, %@ та %lld учасників"; + /* No comment provided by engineer. */ "%@, %@ and %lld other members connected" = "%@, %@ та %lld інші підключені учасники"; @@ -175,12 +187,27 @@ /* No comment provided by engineer. */ "%lld file(s) with total size of %@" = "%lld файл(и) загальним розміром %@"; +/* No comment provided by engineer. */ +"%lld group events" = "%lld групові заходи"; + /* No comment provided by engineer. */ "%lld members" = "%lld учасників"; +/* No comment provided by engineer. */ +"%lld messages blocked" = "%lld повідомлень заблоковано"; + +/* No comment provided by engineer. */ +"%lld messages marked deleted" = "%lld повідомлень позначено як видалені"; + +/* No comment provided by engineer. */ +"%lld messages moderated by %@" = "%lld повідомлень модерує %@"; + /* No comment provided by engineer. */ "%lld minutes" = "%lld хвилин"; +/* No comment provided by engineer. */ +"%lld new interface languages" = "%lld нові мови інтерфейсу"; + /* No comment provided by engineer. */ "%lld second(s)" = "%lld секунд(и)"; @@ -223,6 +250,9 @@ /* No comment provided by engineer. */ "~strike~" = "\\~закреслити~"; +/* time to disappear */ +"0 sec" = "0 сек"; + /* No comment provided by engineer. */ "0s" = "0с"; @@ -241,9 +271,6 @@ /* time interval */ "1 week" = "1 тиждень"; -/* No comment provided by engineer. */ -"1-time link" = "1-разове посилання"; - /* No comment provided by engineer. */ "5 minutes" = "5 хвилин"; @@ -365,6 +392,9 @@ /* No comment provided by engineer. */ "All messages will be deleted - this cannot be undone! The messages will be deleted ONLY for you." = "Всі повідомлення будуть видалені - це неможливо скасувати! Повідомлення будуть видалені ТІЛЬКИ для вас."; +/* No comment provided by engineer. */ +"All new messages from %@ will be hidden!" = "Всі нові повідомлення від %@ будуть приховані!"; + /* No comment provided by engineer. */ "All your contacts will remain connected." = "Всі ваші контакти залишаться на зв'язку."; @@ -381,7 +411,7 @@ "Allow disappearing messages only if your contact allows it to you." = "Дозволяйте зникати повідомленням, тільки якщо контакт дозволяє вам це робити."; /* No comment provided by engineer. */ -"Allow irreversible message deletion only if your contact allows it to you." = "Дозволяйте безповоротне видалення повідомлень, тільки якщо контакт дозволяє вам це зробити."; +"Allow irreversible message deletion only if your contact allows it to you. (24 hours)" = "Дозволяйте безповоротне видалення повідомлень, тільки якщо контакт дозволяє вам це зробити. (24 години)"; /* No comment provided by engineer. */ "Allow message reactions only if your contact allows them." = "Дозволяйте реакції на повідомлення, тільки якщо ваш контакт дозволяє їх."; @@ -396,7 +426,7 @@ "Allow sending disappearing messages." = "Дозволити надсилання зникаючих повідомлень."; /* No comment provided by engineer. */ -"Allow to irreversibly delete sent messages." = "Дозволяє безповоротно видаляти надіслані повідомлення."; +"Allow to irreversibly delete sent messages. (24 hours)" = "Дозволяє безповоротно видаляти надіслані повідомлення. (24 години)"; /* No comment provided by engineer. */ "Allow to send files and media." = "Дозволяє надсилати файли та медіа."; @@ -417,7 +447,7 @@ "Allow your contacts to call you." = "Дозвольте вашим контактам телефонувати вам."; /* No comment provided by engineer. */ -"Allow your contacts to irreversibly delete sent messages." = "Дозвольте вашим контактам безповоротно видаляти надіслані повідомлення."; +"Allow your contacts to irreversibly delete sent messages. (24 hours)" = "Дозвольте вашим контактам безповоротно видаляти надіслані повідомлення. (24 години)"; /* No comment provided by engineer. */ "Allow your contacts to send disappearing messages." = "Дозвольте своїм контактам надсилати зникаючі повідомлення."; @@ -428,6 +458,12 @@ /* No comment provided by engineer. */ "Already connected?" = "Вже підключено?"; +/* No comment provided by engineer. */ +"Already connecting!" = "Вже підключаємось!"; + +/* No comment provided by engineer. */ +"Already joining the group!" = "Вже приєднуємося до групи!"; + /* pref value */ "always" = "завжди"; @@ -443,6 +479,9 @@ /* No comment provided by engineer. */ "App build: %@" = "Збірка програми: %@"; +/* No comment provided by engineer. */ +"App encrypts new local files (except videos)." = "Додаток шифрує нові локальні файли (крім відео)."; + /* No comment provided by engineer. */ "App icon" = "Іконка програми"; @@ -503,6 +542,9 @@ /* No comment provided by engineer. */ "Back" = "Назад"; +/* No comment provided by engineer. */ +"Bad desktop address" = "Неправильна адреса робочого столу"; + /* integrity error chat item */ "bad message hash" = "невірний хеш повідомлення"; @@ -515,9 +557,24 @@ /* No comment provided by engineer. */ "Bad message ID" = "Неправильний ідентифікатор повідомлення"; +/* No comment provided by engineer. */ +"Better groups" = "Кращі групи"; + /* No comment provided by engineer. */ "Better messages" = "Кращі повідомлення"; +/* No comment provided by engineer. */ +"Block" = "Блокувати"; + +/* No comment provided by engineer. */ +"Block group members" = "Учасники групи блокування"; + +/* No comment provided by engineer. */ +"Block member" = "Заблокувати користувача"; + +/* No comment provided by engineer. */ +"Block member?" = "Заблокувати користувача?"; + /* No comment provided by engineer. */ "bold" = "жирний"; @@ -525,7 +582,7 @@ "Both you and your contact can add message reactions." = "Реакції на повідомлення можете додавати як ви, так і ваш контакт."; /* No comment provided by engineer. */ -"Both you and your contact can irreversibly delete sent messages." = "І ви, і ваш контакт можете безповоротно видалити надіслані повідомлення."; +"Both you and your contact can irreversibly delete sent messages. (24 hours)" = "І ви, і ваш контакт можете безповоротно видалити надіслані повідомлення. (24 години)"; /* No comment provided by engineer. */ "Both you and your contact can make calls." = "Дзвонити можете як ви, так і ваш контакт."; @@ -536,6 +593,9 @@ /* No comment provided by engineer. */ "Both you and your contact can send voice messages." = "Надсилати голосові повідомлення можете як ви, так і ваш контакт."; +/* No comment provided by engineer. */ +"Bulgarian, Finnish, Thai and Ukrainian - thanks to the users and [Weblate](https://github.com/simplex-chat/simplex-chat/tree/stable#help-translating-simplex-chat)!" = "Болгарською, фінською, тайською та українською мовами - завдяки користувачам та [Weblate](https://github.com/simplex-chat/simplex-chat/tree/stable#help-translating-simplex-chat)!"; + /* No comment provided by engineer. */ "By chat profile (default) or [by connection](https://simplex.chat/blog/20230204-simplex-chat-v4-5-user-chat-profiles.html#transport-isolation) (BETA)." = "Через профіль чату (за замовчуванням) або [за з'єднанням](https://simplex.chat/blog/20230204-simplex-chat-v4-5-user-chat-profiles.html#transport-isolation) (BETA)."; @@ -554,9 +614,6 @@ /* No comment provided by engineer. */ "Calls" = "Дзвінки"; -/* No comment provided by engineer. */ -"Can't delete user profile!" = "Не можу видалити профіль користувача!"; - /* No comment provided by engineer. */ "Can't invite contact!" = "Не вдається запросити контакт!"; @@ -708,24 +765,45 @@ /* server test step */ "Connect" = "Підключіться"; +/* No comment provided by engineer. */ +"Connect automatically" = "Підключення автоматично"; + /* No comment provided by engineer. */ "Connect incognito" = "Підключайтеся інкогніто"; +/* No comment provided by engineer. */ +"Connect to desktop" = "Підключення до комп'ютера"; + /* No comment provided by engineer. */ "connect to SimpleX Chat developers." = "зв'язатися з розробниками SimpleX Chat."; /* No comment provided by engineer. */ -"Connect via link" = "Підключіться за посиланням"; +"Connect to yourself?" = "З'єднатися з самим собою?"; /* No comment provided by engineer. */ -"Connect via link / QR code" = "Підключитися за посиланням / QR-кодом"; +"Connect to yourself?\nThis is your own one-time link!" = "Підключитися до себе? \nЦе ваше власне одноразове посилання!"; + +/* No comment provided by engineer. */ +"Connect to yourself?\nThis is your own SimpleX address!" = "З'єднатися з самим собою? \nЦе ваша власна SimpleX-адреса!"; + +/* No comment provided by engineer. */ +"Connect via contact address" = "Підключіться за контактною адресою"; + +/* No comment provided by engineer. */ +"Connect via link" = "Підключіться за посиланням"; /* No comment provided by engineer. */ "Connect via one-time link" = "Під'єднатися за одноразовим посиланням"; +/* No comment provided by engineer. */ +"Connect with %@" = "Підключитися до %@"; + /* No comment provided by engineer. */ "connected" = "з'єднаний"; +/* No comment provided by engineer. */ +"Connected desktop" = "Підключений робочий стіл"; + /* No comment provided by engineer. */ "connecting" = "з'єднання"; @@ -831,9 +909,6 @@ /* No comment provided by engineer. */ "Create link" = "Створити посилання"; -/* No comment provided by engineer. */ -"Create one-time invitation link" = "Створіть одноразове посилання-запрошення"; - /* server test step */ "Create queue" = "Створити чергу"; @@ -1588,7 +1663,7 @@ "Group members can add message reactions." = "Учасники групи можуть додавати реакції на повідомлення."; /* No comment provided by engineer. */ -"Group members can irreversibly delete sent messages." = "Учасники групи можуть безповоротно видаляти надіслані повідомлення."; +"Group members can irreversibly delete sent messages. (24 hours)" = "Учасники групи можуть безповоротно видаляти надіслані повідомлення. (24 години)"; /* No comment provided by engineer. */ "Group members can send direct messages." = "Учасники групи можуть надсилати прямі повідомлення."; @@ -1680,9 +1755,6 @@ /* No comment provided by engineer. */ "If you can't meet in person, show QR code in a video call, or share the link." = "Якщо ви не можете зустрітися особисто, покажіть QR-код у відеодзвінку або поділіться посиланням."; -/* No comment provided by engineer. */ -"If you cannot meet in person, you can **scan QR code in the video call**, or your contact can share an invitation link." = "Якщо ви не можете зустрітися особисто, ви можете **сканувати QR-код у відеодзвінку**, або ваш контакт може поділитися посиланням на запрошення."; - /* No comment provided by engineer. */ "If you enter this passcode when opening the app, all app data will be irreversibly removed!" = "Якщо ви введете цей пароль при відкритті програми, всі дані програми будуть безповоротно видалені!"; @@ -1923,6 +1995,9 @@ /* No comment provided by engineer. */ "Live messages" = "Живі повідомлення"; +/* No comment provided by engineer. */ +"Local" = "Локально"; + /* No comment provided by engineer. */ "Local name" = "Місцева назва"; @@ -2183,9 +2258,6 @@ /* No comment provided by engineer. */ "Off" = "Вимкнено"; -/* No comment provided by engineer. */ -"Off (Local)" = "Вимкнено (локально)"; - /* feature offered item */ "offered %@" = "запропоновано %@"; @@ -2232,7 +2304,7 @@ "Only you can add message reactions." = "Тільки ви можете додавати реакції на повідомлення."; /* No comment provided by engineer. */ -"Only you can irreversibly delete messages (your contact can mark them for deletion)." = "Тільки ви можете безповоротно видалити повідомлення (ваш контакт може позначити їх для видалення)."; +"Only you can irreversibly delete messages (your contact can mark them for deletion). (24 hours)" = "Тільки ви можете безповоротно видалити повідомлення (ваш контакт може позначити їх для видалення). (24 години)"; /* No comment provided by engineer. */ "Only you can make calls." = "Дзвонити можете тільки ви."; @@ -2247,7 +2319,7 @@ "Only your contact can add message reactions." = "Тільки ваш контакт може додавати реакції на повідомлення."; /* No comment provided by engineer. */ -"Only your contact can irreversibly delete messages (you can mark them for deletion)." = "Тільки ваш контакт може безповоротно видалити повідомлення (ви можете позначити їх для видалення)."; +"Only your contact can irreversibly delete messages (you can mark them for deletion). (24 hours)" = "Тільки ваш контакт може безповоротно видалити повідомлення (ви можете позначити їх для видалення). (24 години)"; /* No comment provided by engineer. */ "Only your contact can make calls." = "Тільки ваш контакт може здійснювати дзвінки."; @@ -2273,9 +2345,6 @@ /* No comment provided by engineer. */ "Open-source protocol and code – anybody can run the servers." = "Протокол і код з відкритим вихідним кодом - будь-хто може запускати сервери."; -/* No comment provided by engineer. */ -"Opening database…" = "Відкриття бази даних…"; - /* member role */ "owner" = "власник"; @@ -2297,18 +2366,9 @@ /* No comment provided by engineer. */ "Password to show" = "Показати пароль"; -/* No comment provided by engineer. */ -"Paste" = "Вставити"; - /* No comment provided by engineer. */ "Paste image" = "Вставити зображення"; -/* No comment provided by engineer. */ -"Paste received link" = "Вставте отримане посилання"; - -/* placeholder */ -"Paste the link you received to connect with your contact." = "Вставте отримане посилання для зв'язку з вашим контактом."; - /* No comment provided by engineer. */ "peer-to-peer" = "одноранговий"; @@ -2852,9 +2912,6 @@ /* No comment provided by engineer. */ "Share link" = "Поділіться посиланням"; -/* No comment provided by engineer. */ -"Share one-time invitation link" = "Поділіться посиланням на одноразове запрошення"; - /* No comment provided by engineer. */ "Share with contacts" = "Поділіться з контактами"; @@ -2927,9 +2984,6 @@ /* notification title */ "Somebody" = "Хтось"; -/* No comment provided by engineer. */ -"Start a new chat" = "Почніть новий чат"; - /* No comment provided by engineer. */ "Start chat" = "Почати чат"; @@ -3089,12 +3143,6 @@ /* No comment provided by engineer. */ "Theme" = "Тема"; -/* No comment provided by engineer. */ -"There should be at least one user profile." = "Повинен бути принаймні один профіль користувача."; - -/* No comment provided by engineer. */ -"There should be at least one visible user profile." = "Повинен бути принаймні один видимий профіль користувача."; - /* No comment provided by engineer. */ "These settings are for your current profile **%@**." = "Ці налаштування стосуються вашого поточного профілю **%@**."; @@ -3164,9 +3212,6 @@ /* No comment provided by engineer. */ "Turn off" = "Вимкнути"; -/* No comment provided by engineer. */ -"Turn off notifications?" = "Вимкнути сповіщення?"; - /* No comment provided by engineer. */ "Turn on" = "Ввімкнути"; @@ -3434,9 +3479,6 @@ /* No comment provided by engineer. */ "You can accept calls from lock screen, without device and app authentication." = "Ви можете приймати дзвінки з екрана блокування без автентифікації пристрою та програми."; -/* No comment provided by engineer. */ -"You can also connect by clicking the link. If it opens in the browser, click **Open in mobile app** button." = "Ви також можете підключитися за посиланням. Якщо воно відкриється в браузері, натисніть кнопку **Відкрити в мобільному додатку**."; - /* No comment provided by engineer. */ "You can create it later" = "Ви можете створити його пізніше"; @@ -3587,9 +3629,6 @@ /* No comment provided by engineer. */ "Your contacts can allow full message deletion." = "Ваші контакти можуть дозволити повне видалення повідомлень."; -/* No comment provided by engineer. */ -"Your contacts in SimpleX will see it.\nYou can change it in Settings." = "Ваші контакти в SimpleX побачать це.\nВи можете змінити його в Налаштуваннях."; - /* No comment provided by engineer. */ "Your contacts will remain connected." = "Ваші контакти залишаться на зв'язку."; diff --git a/apps/ios/zh-Hans.lproj/Localizable.strings b/apps/ios/zh-Hans.lproj/Localizable.strings index c106e27f23..8ed4cb7c7e 100644 --- a/apps/ios/zh-Hans.lproj/Localizable.strings +++ b/apps/ios/zh-Hans.lproj/Localizable.strings @@ -58,9 +58,6 @@ /* No comment provided by engineer. */ "**Add new contact**: to create your one-time QR Code for your contact." = "**添加新联系人**:为您的联系人创建一次性二维码或者链接。"; -/* No comment provided by engineer. */ -"**Create link / QR code** for your contact to use." = "**创建链接 / 二维码** 给您的联系人使用。"; - /* No comment provided by engineer. */ "**e2e encrypted** audio call" = "**端到端加密** 语音通话"; @@ -73,18 +70,12 @@ /* No comment provided by engineer. */ "**Most private**: do not use SimpleX Chat notifications server, check messages periodically in the background (depends on how often you use the app)." = "**最私密**:不使用 SimpleX Chat 通知服务器,在后台定期检查消息(取决于您多经常使用应用程序)。"; -/* No comment provided by engineer. */ -"**Paste received link** or open it in the browser and tap **Open in mobile app**." = "**粘贴收到的链接**或者在浏览器里打开并且点击**在移动应用程序里打开**。"; - /* No comment provided by engineer. */ "**Please note**: you will NOT be able to recover or change passphrase if you lose it." = "**请注意**:如果您丢失密码,您将无法恢复或者更改密码。"; /* No comment provided by engineer. */ "**Recommended**: device token and notifications are sent to SimpleX Chat notification server, but not the message content, size or who it is from." = "**推荐**:设备令牌和通知会发送至 SimpleX Chat 通知服务器,但是消息内容、大小或者发送人不会。"; -/* No comment provided by engineer. */ -"**Scan QR code**: to connect to your contact in person or via video call." = "**扫描二维码**:见面或者通过视频通话来连接您的联系人。"; - /* No comment provided by engineer. */ "**Warning**: Instant push notifications require passphrase saved in Keychain." = "**警告**:及时推送通知需要保存在钥匙串的密码。"; @@ -247,9 +238,6 @@ /* time interval */ "1 week" = "1周"; -/* No comment provided by engineer. */ -"1-time link" = "一次性链接"; - /* No comment provided by engineer. */ "5 minutes" = "5分钟"; @@ -387,7 +375,7 @@ "Allow disappearing messages only if your contact allows it to you." = "仅当您的联系人允许时才允许限时消息。"; /* No comment provided by engineer. */ -"Allow irreversible message deletion only if your contact allows it to you." = "仅有您的联系人许可后才允许不可撤回消息移除。"; +"Allow irreversible message deletion only if your contact allows it to you. (24 hours)" = "仅有您的联系人许可后才允许不可撤回消息移除。"; /* No comment provided by engineer. */ "Allow message reactions only if your contact allows them." = "只有您的联系人允许时才允许消息回应。"; @@ -402,7 +390,7 @@ "Allow sending disappearing messages." = "允许发送限时消息。"; /* No comment provided by engineer. */ -"Allow to irreversibly delete sent messages." = "允许不可撤回地删除已发送消息。"; +"Allow to irreversibly delete sent messages. (24 hours)" = "允许不可撤回地删除已发送消息。"; /* No comment provided by engineer. */ "Allow to send files and media." = "允许发送文件和媒体。"; @@ -423,7 +411,7 @@ "Allow your contacts to call you." = "允许您的联系人给您打电话。"; /* No comment provided by engineer. */ -"Allow your contacts to irreversibly delete sent messages." = "允许您的联系人不可撤回地删除已发送消息。"; +"Allow your contacts to irreversibly delete sent messages. (24 hours)" = "允许您的联系人不可撤回地删除已发送消息。"; /* No comment provided by engineer. */ "Allow your contacts to send disappearing messages." = "允许您的联系人发送限时消息。"; @@ -534,7 +522,7 @@ "Both you and your contact can add message reactions." = "您和您的联系人都可以添加消息回应。"; /* No comment provided by engineer. */ -"Both you and your contact can irreversibly delete sent messages." = "您和您的联系人都可以不可逆转地删除已发送的消息。"; +"Both you and your contact can irreversibly delete sent messages. (24 hours)" = "您和您的联系人都可以不可逆转地删除已发送的消息。"; /* No comment provided by engineer. */ "Both you and your contact can make calls." = "您和您的联系人都可以拨打电话。"; @@ -566,9 +554,6 @@ /* No comment provided by engineer. */ "Calls" = "通话"; -/* No comment provided by engineer. */ -"Can't delete user profile!" = "无法删除用户个人资料!"; - /* No comment provided by engineer. */ "Can't invite contact!" = "无法邀请联系人!"; @@ -729,9 +714,6 @@ /* No comment provided by engineer. */ "Connect via link" = "通过链接连接"; -/* No comment provided by engineer. */ -"Connect via link / QR code" = "通过群组链接/二维码连接"; - /* No comment provided by engineer. */ "Connect via one-time link" = "通过一次性链接连接"; @@ -849,9 +831,6 @@ /* No comment provided by engineer. */ "Create new profile in [desktop app](https://simplex.chat/downloads/). 💻" = "在[桌面应用程序](https://simplex.chat/downloads/)中创建新的个人资料。 💻"; -/* No comment provided by engineer. */ -"Create one-time invitation link" = "创建一次性邀请链接"; - /* server test step */ "Create queue" = "创建队列"; @@ -1624,7 +1603,7 @@ "Group members can add message reactions." = "群组成员可以添加信息回应。"; /* No comment provided by engineer. */ -"Group members can irreversibly delete sent messages." = "群组成员可以不可撤回地删除已发送的消息。"; +"Group members can irreversibly delete sent messages. (24 hours)" = "群组成员可以不可撤回地删除已发送的消息。"; /* No comment provided by engineer. */ "Group members can send direct messages." = "群组成员可以私信。"; @@ -1716,9 +1695,6 @@ /* No comment provided by engineer. */ "If you can't meet in person, show QR code in a video call, or share the link." = "如果您不能亲自见面,可以在视频通话中展示二维码,或分享链接。"; -/* No comment provided by engineer. */ -"If you cannot meet in person, you can **scan QR code in the video call**, or your contact can share an invitation link." = "如果您不能亲自见面,您可以**扫描视频通话中的二维码**,或者您的联系人可以分享邀请链接。"; - /* No comment provided by engineer. */ "If you enter this passcode when opening the app, all app data will be irreversibly removed!" = "如果您在打开应用时输入该密码,所有应用程序数据将被不可撤回地删除!"; @@ -1959,6 +1935,9 @@ /* No comment provided by engineer. */ "Live messages" = "实时消息"; +/* No comment provided by engineer. */ +"Local" = "本地"; + /* No comment provided by engineer. */ "Local name" = "本地名称"; @@ -2222,9 +2201,6 @@ /* No comment provided by engineer. */ "Off" = "关闭"; -/* No comment provided by engineer. */ -"Off (Local)" = "关闭(本地)"; - /* feature offered item */ "offered %@" = "已提供 %@"; @@ -2271,7 +2247,7 @@ "Only you can add message reactions." = "只有您可以添加消息回应。"; /* No comment provided by engineer. */ -"Only you can irreversibly delete messages (your contact can mark them for deletion)." = "只有您可以不可撤回地删除消息(您的联系人可以将它们标记为删除)。"; +"Only you can irreversibly delete messages (your contact can mark them for deletion). (24 hours)" = "只有您可以不可撤回地删除消息(您的联系人可以将它们标记为删除)。"; /* No comment provided by engineer. */ "Only you can make calls." = "只有您可以拨打电话。"; @@ -2286,7 +2262,7 @@ "Only your contact can add message reactions." = "只有您的联系人可以添加消息回应。"; /* No comment provided by engineer. */ -"Only your contact can irreversibly delete messages (you can mark them for deletion)." = "只有您的联系人才能不可撤回地删除消息(您可以将它们标记为删除)。"; +"Only your contact can irreversibly delete messages (you can mark them for deletion). (24 hours)" = "只有您的联系人才能不可撤回地删除消息(您可以将它们标记为删除)。"; /* No comment provided by engineer. */ "Only your contact can make calls." = "只有您的联系人可以拨打电话。"; @@ -2315,9 +2291,6 @@ /* No comment provided by engineer. */ "Open-source protocol and code – anybody can run the servers." = "开源协议和代码——任何人都可以运行服务器。"; -/* No comment provided by engineer. */ -"Opening database…" = "打开数据库中……"; - /* member role */ "owner" = "群主"; @@ -2339,18 +2312,9 @@ /* No comment provided by engineer. */ "Password to show" = "显示密码"; -/* No comment provided by engineer. */ -"Paste" = "粘贴"; - /* No comment provided by engineer. */ "Paste image" = "粘贴图片"; -/* No comment provided by engineer. */ -"Paste received link" = "粘贴收到的链接"; - -/* placeholder */ -"Paste the link you received to connect with your contact." = "将您收到的链接粘贴到下面的框中以与您的联系人联系。"; - /* No comment provided by engineer. */ "peer-to-peer" = "点对点"; @@ -2900,9 +2864,6 @@ /* No comment provided by engineer. */ "Share link" = "分享链接"; -/* No comment provided by engineer. */ -"Share one-time invitation link" = "分享一次性邀请链接"; - /* No comment provided by engineer. */ "Share with contacts" = "与联系人分享"; @@ -2978,9 +2939,6 @@ /* notification title */ "Somebody" = "某人"; -/* No comment provided by engineer. */ -"Start a new chat" = "开始新聊天"; - /* No comment provided by engineer. */ "Start chat" = "开始聊天"; @@ -3140,12 +3098,6 @@ /* No comment provided by engineer. */ "Theme" = "主题"; -/* No comment provided by engineer. */ -"There should be at least one user profile." = "应该至少有一个用户资料。"; - -/* No comment provided by engineer. */ -"There should be at least one visible user profile." = "应该至少有一个可见的用户资料。"; - /* No comment provided by engineer. */ "These settings are for your current profile **%@**." = "这些设置适用于您当前的配置文件 **%@**。"; @@ -3218,9 +3170,6 @@ /* No comment provided by engineer. */ "Turn off" = "关闭"; -/* No comment provided by engineer. */ -"Turn off notifications?" = "关闭通知?"; - /* No comment provided by engineer. */ "Turn on" = "打开"; @@ -3488,9 +3437,6 @@ /* No comment provided by engineer. */ "You can accept calls from lock screen, without device and app authentication." = "您可以从锁屏上接听电话,无需设备和应用程序的认证。"; -/* No comment provided by engineer. */ -"You can also connect by clicking the link. If it opens in the browser, click **Open in mobile app** button." = "您也可以通过点击链接进行连接。如果在浏览器中打开,请点击“在移动应用程序中打开”按钮。"; - /* No comment provided by engineer. */ "You can create it later" = "您可以以后创建它"; @@ -3641,9 +3587,6 @@ /* No comment provided by engineer. */ "Your contacts can allow full message deletion." = "您的联系人可以允许完全删除消息。"; -/* No comment provided by engineer. */ -"Your contacts in SimpleX will see it.\nYou can change it in Settings." = "您的 SimpleX 的联系人会看到它。\n您可以在设置中更改它。"; - /* No comment provided by engineer. */ "Your contacts will remain connected." = "与您的联系人保持连接。"; diff --git a/apps/multiplatform/android/build.gradle.kts b/apps/multiplatform/android/build.gradle.kts index a9909d2f6f..0c77bdbe62 100644 --- a/apps/multiplatform/android/build.gradle.kts +++ b/apps/multiplatform/android/build.gradle.kts @@ -91,6 +91,7 @@ android { "es", "fi", "fr", + "hu", "it", "iw", "ja", @@ -99,6 +100,7 @@ android { "pt-rBR", "ru", "th", + "tr", "uk", "zh-rCN" ) diff --git a/apps/multiplatform/android/src/main/java/chat/simplex/app/MessagesFetcherWorker.kt b/apps/multiplatform/android/src/main/java/chat/simplex/app/MessagesFetcherWorker.kt index 3b8902b58c..0152f5e8c2 100644 --- a/apps/multiplatform/android/src/main/java/chat/simplex/app/MessagesFetcherWorker.kt +++ b/apps/multiplatform/android/src/main/java/chat/simplex/app/MessagesFetcherWorker.kt @@ -3,11 +3,12 @@ package chat.simplex.app import android.content.Context import android.util.Log import androidx.work.* -import chat.simplex.app.* import chat.simplex.app.SimplexService.Companion.showPassphraseNotification import chat.simplex.common.model.ChatController import chat.simplex.common.views.helpers.DBMigrationResult -import chat.simplex.app.BuildConfig +import chat.simplex.common.platform.chatModel +import chat.simplex.common.platform.initChatControllerAndRunMigrations +import chat.simplex.common.views.helpers.DatabaseUtils import kotlinx.coroutines.* import java.util.Date import java.util.concurrent.TimeUnit @@ -57,6 +58,10 @@ class MessagesFetcherWork( val durationSeconds = inputData.getInt(INPUT_DATA_DURATION, 60) var shouldReschedule = true try { + // In case of self-destruct is enabled the initialization process will not start in SimplexApp, Let's start it here + if (DatabaseUtils.ksSelfDestructPassword.get() != null && chatModel.chatDbStatus.value == null) { + initChatControllerAndRunMigrations() + } withTimeout(durationSeconds * 1000L) { val chatController = ChatController SimplexService.waitDbMigrationEnds(chatController) diff --git a/apps/multiplatform/android/src/main/java/chat/simplex/app/SimplexApp.kt b/apps/multiplatform/android/src/main/java/chat/simplex/app/SimplexApp.kt index 794adfdaf6..f9c2eac134 100644 --- a/apps/multiplatform/android/src/main/java/chat/simplex/app/SimplexApp.kt +++ b/apps/multiplatform/android/src/main/java/chat/simplex/app/SimplexApp.kt @@ -1,6 +1,9 @@ package chat.simplex.app import android.app.Application +import android.content.Context +import androidx.compose.ui.platform.ClipboardManager +import chat.simplex.common.platform.Log import android.app.UiModeManager import android.os.* import androidx.lifecycle.* @@ -43,8 +46,8 @@ class SimplexApp: Application(), LifecycleEventObserver { try { Looper.loop() } catch (e: Throwable) { - if (e.message != null && e.message!!.startsWith("Unable to start activity")) { - android.os.Process.killProcess(android.os.Process.myPid()) + if (e is UnsatisfiedLinkError || e.message?.startsWith("Unable to start activity") == true) { + Process.killProcess(Process.myPid()) break } else { // Send it to our exception handled because it will not get the exception otherwise @@ -60,16 +63,15 @@ class SimplexApp: Application(), LifecycleEventObserver { tmpDir.deleteRecursively() tmpDir.mkdir() - withBGApi { - initChatController() - runMigrations() + if (DatabaseUtils.ksSelfDestructPassword.get() == null) { + initChatControllerAndRunMigrations() } ProcessLifecycleOwner.get().lifecycle.addObserver(this@SimplexApp) } override fun onStateChanged(source: LifecycleOwner, event: Lifecycle.Event) { Log.d(TAG, "onStateChanged: $event") - withApi { + withBGApi { when (event) { Lifecycle.Event.ON_START -> { isAppOnForeground = true @@ -95,6 +97,13 @@ class SimplexApp: Application(), LifecycleEventObserver { } Lifecycle.Event.ON_RESUME -> { isAppOnForeground = true + /** + * When the app calls [ClipboardManager.shareText] and a user copies text in clipboard, Android denies + * access to clipboard because the app considered in background. + * This will ensure that the app will get the event on resume + * */ + val service = androidAppContext.getSystemService(Context.CLIPBOARD_SERVICE) as android.content.ClipboardManager + chatModel.clipboardHasText.value = service.hasPrimaryClip() if (chatModel.controller.appPrefs.onboardingStage.get() == OnboardingStage.OnboardingComplete && chatModel.currentUser.value != null) { SimplexService.showBackgroundServiceNoticeIfNeeded() } diff --git a/apps/multiplatform/android/src/main/java/chat/simplex/app/SimplexService.kt b/apps/multiplatform/android/src/main/java/chat/simplex/app/SimplexService.kt index 2cb6c12da0..dd760e0b19 100644 --- a/apps/multiplatform/android/src/main/java/chat/simplex/app/SimplexService.kt +++ b/apps/multiplatform/android/src/main/java/chat/simplex/app/SimplexService.kt @@ -13,7 +13,6 @@ import androidx.compose.runtime.* import androidx.compose.ui.Modifier import androidx.compose.ui.text.font.FontWeight import androidx.compose.ui.unit.dp -import chat.simplex.common.platform.Log import androidx.core.app.NotificationCompat import androidx.core.content.ContextCompat import androidx.work.* @@ -21,12 +20,13 @@ import chat.simplex.common.AppLock import chat.simplex.common.helpers.requiresIgnoringBattery import chat.simplex.common.model.ChatController import chat.simplex.common.model.NotificationsMode -import chat.simplex.common.platform.androidAppContext +import chat.simplex.common.platform.* import chat.simplex.common.views.helpers.* import kotlinx.coroutines.* import chat.simplex.res.MR import dev.icerock.moko.resources.compose.painterResource import dev.icerock.moko.resources.compose.stringResource +import kotlin.system.exitProcess // based on: // https://robertohuertas.com/2019/06/29/android_foreground_services/ @@ -72,6 +72,10 @@ class SimplexService: Service() { stopSelf() } else { isServiceStarted = true + // In case of self-destruct is enabled the initialization process will not start in SimplexApp, Let's start it here + if (DatabaseUtils.ksSelfDestructPassword.get() != null && chatModel.chatDbStatus.value == null) { + initChatControllerAndRunMigrations() + } } } @@ -100,7 +104,7 @@ class SimplexService: Service() { if (wakeLock != null || isStartingService) return val self = this isStartingService = true - withApi { + withLongRunningApi(slow = 30_000, deadlock = 60_000) { val chatController = ChatController waitDbMigrationEnds(chatController) try { @@ -110,7 +114,7 @@ class SimplexService: Service() { Log.w(chat.simplex.app.TAG, "SimplexService: problem with the database: $chatDbStatus") showPassphraseNotification(chatDbStatus) safeStopService() - return@withApi + return@withLongRunningApi } saveServiceState(self, ServiceState.STARTED) wakeLock = (getSystemService(Context.POWER_SERVICE) as PowerManager).run { @@ -173,6 +177,11 @@ class SimplexService: Service() { // Just to make sure that after restart of the app the user will need to re-authenticate AppLock.clearAuthState() + if (appPreferences.chatStopped.get()) { + stopSelf() + exitProcess(0) + } + // If notification service isn't enabled or battery optimization isn't disabled, we shouldn't restart the service if (!SimplexApp.context.allowToStartServiceAfterAppExit()) { return diff --git a/apps/multiplatform/android/src/main/java/chat/simplex/app/views/call/IncomingCallActivity.kt b/apps/multiplatform/android/src/main/java/chat/simplex/app/views/call/IncomingCallActivity.kt index f5c46a0eb5..d09cb019f8 100644 --- a/apps/multiplatform/android/src/main/java/chat/simplex/app/views/call/IncomingCallActivity.kt +++ b/apps/multiplatform/android/src/main/java/chat/simplex/app/views/call/IncomingCallActivity.kt @@ -97,7 +97,8 @@ fun IncomingCallActivityView(m: ChatModel) { Surface( Modifier .fillMaxSize(), - color = MaterialTheme.colors.background + color = MaterialTheme.colors.background, + contentColor = LocalContentColor.current ) { if (showCallView) { Box { @@ -200,7 +201,8 @@ private fun SimpleXLogo() { private fun LockScreenCallButton(text: String, icon: Painter, color: Color, action: () -> Unit) { Surface( shape = RoundedCornerShape(10.dp), - color = Color.Transparent + color = Color.Transparent, + contentColor = LocalContentColor.current ) { Column( Modifier @@ -227,7 +229,8 @@ fun PreviewIncomingCallLockScreenAlert() { Surface( Modifier .fillMaxSize(), - color = MaterialTheme.colors.background + color = MaterialTheme.colors.background, + contentColor = LocalContentColor.current ) { IncomingCallLockScreenAlertLayout( invitation = RcvCallInvitation( diff --git a/apps/multiplatform/common/build.gradle.kts b/apps/multiplatform/common/build.gradle.kts index 4d2eeca2ee..3b6975638a 100644 --- a/apps/multiplatform/common/build.gradle.kts +++ b/apps/multiplatform/common/build.gradle.kts @@ -154,8 +154,10 @@ afterEvaluate { val endStringRegex = Regex("</string>[ ]*") val endTagRegex = Regex("</") val anyHtmlRegex = Regex("[^>]*>.*(<|>).*</string>|[^>]*>.*(<|>).*</string>") + val fontLtGtRegex = Regex("[^>]*>.*<font[^>]*>.*</font>.*</string>") + val unbracketedColorRegex = Regex("color=#[abcdefABCDEF0-9]{3,6}") val correctHtmlRegex = Regex("[^>]*>.*<b>.*</b>.*</string>|[^>]*>.*<i>.*</i>.*</string>|[^>]*>.*<u>.*</u>.*</string>|[^>]*>.*<font[^>]*>.*</font>.*</string>") - val possibleFormat = listOf("s", "d", "1\$s", "1\$d", "2s", "f") + val possibleFormat = listOf("s", "d", "1\$s", "2\$s", "3\$s", "4\$s", "1\$d", "2\$d", "3\$d", "4\$d", "2s", "f") fun String.id(): String = replace("<string name=\"", "").trim().substringBefore("\"") @@ -181,7 +183,11 @@ afterEvaluate { substring = substring.substringAfter("%") if (was.length == substring.length) break } - return formats + return if (formats.any { it.startsWith("1$") || it.startsWith("2$") || it.startsWith("3$") || it.startsWith("4$") }) { + formats.sortedBy { it.trim('s', 'd', 'f', '$').toIntOrNull() ?: throw Exception("Formatting don't have positional arguments: $this \nin $filepath") } + } else { + formats + } } fun String.removeCDATA(): String = @@ -194,9 +200,12 @@ afterEvaluate { fun String.addCDATA(filepath: String): String { //return this if (anyHtmlRegex.matches(this)) { - val countOfStartTag = count { it == '<' } - val countOfEndTag = count { it == '>' } - if (countOfStartTag != countOfEndTag || countOfStartTag != endTagRegex.findAll(this).count() * 2 || !correctHtmlRegex.matches(this)) { + val prepared = if (fontLtGtRegex.matches(this) || unbracketedColorRegex.containsMatchIn(this)) { + replace("<", "<").replace(">", ">").replace(unbracketedColorRegex) { it.value.replace("color=#", "color=\"#") + "\"" } + } else this + val countOfStartTag = prepared.count { it == '<' } + val countOfEndTag = prepared.count { it == '>' } + if (countOfStartTag != countOfEndTag || countOfStartTag != endTagRegex.findAll(prepared).count() * 2 || !correctHtmlRegex.matches(prepared)) { if (debug) { println("Wrong string:") println(this) @@ -206,7 +215,7 @@ afterEvaluate { throw Exception("Wrong string: $this \nin $filepath") } } - val res = replace(startStringRegex) { it.value + "<![CDATA[" }.replace(endStringRegex) { "]]>" + it.value } + val res = prepared.replace(startStringRegex) { it.value + "<![CDATA[" }.replace(endStringRegex) { "]]>" + it.value } if (debug) { println("Changed string:") println(this) diff --git a/apps/multiplatform/common/src/androidMain/kotlin/chat/simplex/common/helpers/SoundPlayer.kt b/apps/multiplatform/common/src/androidMain/kotlin/chat/simplex/common/helpers/SoundPlayer.kt index 25369ffdfd..ff83c10df3 100644 --- a/apps/multiplatform/common/src/androidMain/kotlin/chat/simplex/common/helpers/SoundPlayer.kt +++ b/apps/multiplatform/common/src/androidMain/kotlin/chat/simplex/common/helpers/SoundPlayer.kt @@ -8,9 +8,7 @@ import androidx.core.content.ContextCompat import chat.simplex.common.R import chat.simplex.common.platform.SoundPlayerInterface import chat.simplex.common.platform.androidAppContext -import chat.simplex.common.views.helpers.withScope -import kotlinx.coroutines.CoroutineScope -import kotlinx.coroutines.delay +import kotlinx.coroutines.* object SoundPlayer: SoundPlayerInterface { private var player: MediaPlayer? = null @@ -31,7 +29,7 @@ object SoundPlayer: SoundPlayerInterface { val vibrator = ContextCompat.getSystemService(androidAppContext, Vibrator::class.java) val effect = VibrationEffect.createOneShot(250, VibrationEffect.DEFAULT_AMPLITUDE) playing = true - withScope(scope) { + scope.launch { while (playing) { if (sound) player?.start() vibrator?.vibrate(effect) diff --git a/apps/multiplatform/common/src/androidMain/kotlin/chat/simplex/common/platform/Modifier.android.kt b/apps/multiplatform/common/src/androidMain/kotlin/chat/simplex/common/platform/Modifier.android.kt index 26ada2b7e6..b103367fe8 100644 --- a/apps/multiplatform/common/src/androidMain/kotlin/chat/simplex/common/platform/Modifier.android.kt +++ b/apps/multiplatform/common/src/androidMain/kotlin/chat/simplex/common/platform/Modifier.android.kt @@ -26,3 +26,5 @@ actual fun Modifier.desktopOnExternalDrag( ): Modifier = this actual fun Modifier.onRightClick(action: () -> Unit): Modifier = this + +actual fun Modifier.desktopPointerHoverIconHand(): Modifier = this diff --git a/apps/multiplatform/common/src/androidMain/kotlin/chat/simplex/common/platform/UI.android.kt b/apps/multiplatform/common/src/androidMain/kotlin/chat/simplex/common/platform/UI.android.kt index 371c140133..d360c44b44 100644 --- a/apps/multiplatform/common/src/androidMain/kotlin/chat/simplex/common/platform/UI.android.kt +++ b/apps/multiplatform/common/src/androidMain/kotlin/chat/simplex/common/platform/UI.android.kt @@ -97,12 +97,14 @@ actual class GlobalExceptionsHandler: Thread.UncaughtExceptionHandler { mainActivity.get()?.recreate() } else { mainActivity.get()?.apply { - window - ?.decorView - ?.findViewById<ViewGroup>(android.R.id.content) - ?.removeViewAt(0) - setContent { - AppScreen() + runOnUiThread { + window + ?.decorView + ?.findViewById<ViewGroup>(android.R.id.content) + ?.removeViewAt(0) + setContent { + AppScreen() + } } } } diff --git a/apps/multiplatform/common/src/androidMain/kotlin/chat/simplex/common/platform/VideoPlayer.android.kt b/apps/multiplatform/common/src/androidMain/kotlin/chat/simplex/common/platform/VideoPlayer.android.kt index d3b4609bc4..6ed054cae9 100644 --- a/apps/multiplatform/common/src/androidMain/kotlin/chat/simplex/common/platform/VideoPlayer.android.kt +++ b/apps/multiplatform/common/src/androidMain/kotlin/chat/simplex/common/platform/VideoPlayer.android.kt @@ -33,9 +33,9 @@ actual class VideoPlayer actual constructor( override val duration: MutableState<Long> = mutableStateOf(defaultDuration) override val preview: MutableState<ImageBitmap> = mutableStateOf(defaultPreview) - init { - setPreviewAndDuration() - } + + // Currently unused because we use low-quality preview + // init { setPreviewAndDuration() } val player = ExoPlayer.Builder(androidAppContext, DefaultRenderersFactory(androidAppContext)) @@ -69,7 +69,7 @@ actual class VideoPlayer actual constructor( } private fun start(seek: Long? = null, onProgressUpdate: (position: Long?, state: TrackState) -> Unit): Boolean { - val filepath = getAppFilePath(uri) + val filepath = if (uri.scheme == "file") uri.toFile().absolutePath else getAppFilePath(uri) if (filepath == null || !File(filepath).exists()) { Log.e(TAG, "No such file: $filepath") brokenVideo.value = true diff --git a/apps/multiplatform/common/src/androidMain/kotlin/chat/simplex/common/views/call/CallView.android.kt b/apps/multiplatform/common/src/androidMain/kotlin/chat/simplex/common/views/call/CallView.android.kt index 5f30d21bb9..ac14b5199f 100644 --- a/apps/multiplatform/common/src/androidMain/kotlin/chat/simplex/common/views/call/CallView.android.kt +++ b/apps/multiplatform/common/src/androidMain/kotlin/chat/simplex/common/views/call/CallView.android.kt @@ -383,7 +383,7 @@ private fun DisabledBackgroundCallsButton() { Modifier .padding(bottom = 24.dp) .clickable { - withBGApi { + withLongRunningApi { show = !platform.androidAskToAllowBackgroundCalls() } } diff --git a/apps/multiplatform/common/src/androidMain/kotlin/chat/simplex/common/views/chat/item/ChatItemView.android.kt b/apps/multiplatform/common/src/androidMain/kotlin/chat/simplex/common/views/chat/item/ChatItemView.android.kt index 3aa4a92619..140b6d12a3 100644 --- a/apps/multiplatform/common/src/androidMain/kotlin/chat/simplex/common/views/chat/item/ChatItemView.android.kt +++ b/apps/multiplatform/common/src/androidMain/kotlin/chat/simplex/common/views/chat/item/ChatItemView.android.kt @@ -13,8 +13,7 @@ import chat.simplex.common.model.ChatItem import chat.simplex.common.model.MsgContent import chat.simplex.common.platform.FileChooserLauncher import chat.simplex.common.platform.saveImage -import chat.simplex.common.views.helpers.SharedContent -import chat.simplex.common.views.helpers.withApi +import chat.simplex.common.views.helpers.* import chat.simplex.res.MR import com.google.accompanist.permissions.rememberPermissionState import dev.icerock.moko.resources.compose.painterResource @@ -37,7 +36,7 @@ actual fun SaveContentItemAction(cItem: ChatItem, saveFileLauncher: FileChooserL writePermissionState.launchPermissionRequest() } } - is MsgContent.MCFile, is MsgContent.MCVoice, is MsgContent.MCVideo -> withApi { saveFileLauncher.launch(cItem.file?.fileName ?: "") } + is MsgContent.MCFile, is MsgContent.MCVoice, is MsgContent.MCVideo -> withLongRunningApi { saveFileLauncher.launch(cItem.file?.fileName ?: "") } else -> {} } showMenu.value = false diff --git a/apps/multiplatform/common/src/androidMain/kotlin/chat/simplex/common/views/chatlist/ChatListNavLinkView.android.kt b/apps/multiplatform/common/src/androidMain/kotlin/chat/simplex/common/views/chatlist/ChatListNavLinkView.android.kt index 30f5b81387..f0f733111a 100644 --- a/apps/multiplatform/common/src/androidMain/kotlin/chat/simplex/common/views/chatlist/ChatListNavLinkView.android.kt +++ b/apps/multiplatform/common/src/androidMain/kotlin/chat/simplex/common/views/chatlist/ChatListNavLinkView.android.kt @@ -16,11 +16,12 @@ actual fun ChatListNavLinkLayout( click: () -> Unit, dropdownMenuItems: (@Composable () -> Unit)?, showMenu: MutableState<Boolean>, - stopped: Boolean, - selectedChat: State<Boolean> + disabled: Boolean, + selectedChat: State<Boolean>, + nextChatSelected: State<Boolean>, ) { var modifier = Modifier.fillMaxWidth() - if (!stopped) modifier = modifier + if (!disabled) modifier = modifier .combinedClickable(onClick = click, onLongClick = { showMenu.value = true }) .onRightClick { showMenu.value = true } Box(modifier) { diff --git a/apps/multiplatform/common/src/androidMain/kotlin/chat/simplex/common/views/helpers/Utils.android.kt b/apps/multiplatform/common/src/androidMain/kotlin/chat/simplex/common/views/helpers/Utils.android.kt index d244294763..904f9a555a 100644 --- a/apps/multiplatform/common/src/androidMain/kotlin/chat/simplex/common/views/helpers/Utils.android.kt +++ b/apps/multiplatform/common/src/androidMain/kotlin/chat/simplex/common/views/helpers/Utils.android.kt @@ -1,5 +1,7 @@ package chat.simplex.common.views.helpers +import android.content.ClipboardManager +import android.content.Context import android.content.res.Resources import android.graphics.* import android.graphics.Typeface @@ -12,6 +14,7 @@ import android.text.SpannedString import android.text.style.* import android.util.Base64 import android.view.WindowManager +import androidx.compose.runtime.* import androidx.compose.ui.graphics.* import androidx.compose.ui.graphics.Color import androidx.compose.ui.text.* @@ -24,7 +27,6 @@ import androidx.core.text.HtmlCompat import chat.simplex.common.helpers.* import chat.simplex.common.model.* import chat.simplex.common.platform.* -import chat.simplex.res.MR import dev.icerock.moko.resources.StringResource import java.io.* import java.net.URI @@ -55,6 +57,19 @@ fun keepScreenOn(on: Boolean) { } } +@Composable +actual fun SetupClipboardListener() { + DisposableEffect(Unit) { + val service = androidAppContext.getSystemService(Context.CLIPBOARD_SERVICE) as ClipboardManager + val listener = { chatModel.clipboardHasText.value = service.hasPrimaryClip() } + chatModel.clipboardHasText.value = service.hasPrimaryClip() + service.addPrimaryClipChangedListener(listener) + onDispose { + service.removePrimaryClipChangedListener(listener) + } + } +} + actual fun escapedHtmlToAnnotatedString(text: String, density: Density): AnnotatedString { return spannableStringToAnnotatedString(HtmlCompat.fromHtml(text, HtmlCompat.FROM_HTML_MODE_LEGACY), density) } diff --git a/apps/multiplatform/common/src/androidMain/kotlin/chat/simplex/common/views/newchat/ConnectViaLinkView.android.kt b/apps/multiplatform/common/src/androidMain/kotlin/chat/simplex/common/views/newchat/ConnectViaLinkView.android.kt deleted file mode 100644 index e5a7ae40a5..0000000000 --- a/apps/multiplatform/common/src/androidMain/kotlin/chat/simplex/common/views/newchat/ConnectViaLinkView.android.kt +++ /dev/null @@ -1,68 +0,0 @@ -package chat.simplex.common.views.newchat - -import androidx.compose.foundation.layout.* -import androidx.compose.material.* -import androidx.compose.runtime.* -import androidx.compose.ui.Modifier -import androidx.compose.ui.graphics.Color -import dev.icerock.moko.resources.compose.painterResource -import dev.icerock.moko.resources.compose.stringResource -import androidx.compose.ui.unit.sp -import chat.simplex.common.model.ChatModel -import chat.simplex.common.model.RemoteHostInfo -import chat.simplex.res.MR - -@Composable -actual fun ConnectViaLinkView(m: ChatModel, rh: RemoteHostInfo?, close: () -> Unit) { - // TODO this should close if remote host changes in model - val selection = remember { - mutableStateOf( - runCatching { ConnectViaLinkTab.valueOf(m.controller.appPrefs.connectViaLinkTab.get()!!) }.getOrDefault(ConnectViaLinkTab.SCAN) - ) - } - val tabTitles = ConnectViaLinkTab.values().map { - when (it) { - ConnectViaLinkTab.SCAN -> stringResource(MR.strings.scan_QR_code) - ConnectViaLinkTab.PASTE -> stringResource(MR.strings.paste_the_link_you_received) - } - } - Column( - Modifier.fillMaxHeight(), - verticalArrangement = Arrangement.SpaceBetween - ) { - Column(Modifier.weight(1f)) { - when (selection.value) { - ConnectViaLinkTab.SCAN -> { - ScanToConnectView(m, rh, close) - } - ConnectViaLinkTab.PASTE -> { - PasteToConnectView(m, rh, close) - } - } - } - TabRow( - selectedTabIndex = selection.value.ordinal, - backgroundColor = Color.Transparent, - contentColor = MaterialTheme.colors.primary, - ) { - tabTitles.forEachIndexed { index, it -> - Tab( - selected = selection.value.ordinal == index, - onClick = { - selection.value = ConnectViaLinkTab.values()[index] - m.controller.appPrefs.connectViaLinkTab.set(selection.value .name) - }, - text = { Text(it, fontSize = 13.sp) }, - icon = { - Icon( - if (ConnectViaLinkTab.SCAN.ordinal == index) painterResource(MR.images.ic_qr_code) else painterResource(MR.images.ic_article), - it - ) - }, - selectedContentColor = MaterialTheme.colors.primary, - unselectedContentColor = MaterialTheme.colors.secondary, - ) - } - } - } -} diff --git a/apps/multiplatform/common/src/androidMain/kotlin/chat/simplex/common/views/newchat/QRCodeScanner.android.kt b/apps/multiplatform/common/src/androidMain/kotlin/chat/simplex/common/views/newchat/QRCodeScanner.android.kt index e7453ce20a..b8f5abc50e 100644 --- a/apps/multiplatform/common/src/androidMain/kotlin/chat/simplex/common/views/newchat/QRCodeScanner.android.kt +++ b/apps/multiplatform/common/src/androidMain/kotlin/chat/simplex/common/views/newchat/QRCodeScanner.android.kt @@ -2,16 +2,20 @@ package chat.simplex.common.views.newchat import android.Manifest import android.annotation.SuppressLint +import android.content.pm.PackageManager import android.util.Log import android.view.ViewGroup import androidx.camera.core.* import androidx.camera.lifecycle.ProcessCameraProvider import androidx.camera.view.PreviewView +import androidx.compose.foundation.layout.* +import androidx.compose.material.* import androidx.compose.runtime.* +import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier import androidx.compose.ui.draw.clipToBounds -import androidx.compose.ui.platform.LocalContext -import androidx.compose.ui.platform.LocalLifecycleOwner +import androidx.compose.ui.platform.* +import androidx.compose.ui.unit.dp import androidx.compose.ui.viewinterop.AndroidView import androidx.core.content.ContextCompat import boofcv.abst.fiducial.QrCodeDetector @@ -20,18 +24,23 @@ import boofcv.android.ConvertCameraImage import boofcv.factory.fiducial.FactoryFiducial import boofcv.struct.image.GrayU8 import chat.simplex.common.platform.TAG +import chat.simplex.common.ui.theme.DEFAULT_PADDING_HALF +import chat.simplex.common.views.helpers.* +import chat.simplex.res.MR import com.google.accompanist.permissions.rememberPermissionState import com.google.common.util.concurrent.ListenableFuture +import dev.icerock.moko.resources.compose.painterResource +import dev.icerock.moko.resources.compose.stringResource import java.util.concurrent.* // Adapted from learntodroid - https://gist.github.com/learntodroid/8f839be0b29d0378f843af70607bd7f5 @Composable -actual fun QRCodeScanner(onBarcode: (String) -> Unit) { - val cameraPermissionState = rememberPermissionState(permission = Manifest.permission.CAMERA) - LaunchedEffect(Unit) { - cameraPermissionState.launchPermissionRequest() - } +actual fun QRCodeScanner( + showQRCodeScanner: MutableState<Boolean>, + padding: PaddingValues, + onBarcode: (String) -> Unit +) { val context = LocalContext.current val lifecycleOwner = LocalLifecycleOwner.current var preview by remember { mutableStateOf<Preview?>(null) } @@ -48,57 +57,102 @@ actual fun QRCodeScanner(onBarcode: (String) -> Unit) { } } - AndroidView( - factory = { AndroidViewContext -> - PreviewView(AndroidViewContext).apply { - this.scaleType = PreviewView.ScaleType.FILL_CENTER - layoutParams = ViewGroup.LayoutParams( - ViewGroup.LayoutParams.MATCH_PARENT, - ViewGroup.LayoutParams.MATCH_PARENT, - ) - implementationMode = PreviewView.ImplementationMode.COMPATIBLE - } - }, - modifier = Modifier.clipToBounds() - ) { previewView -> - val cameraSelector: CameraSelector = CameraSelector.Builder() - .requireLensFacing(CameraSelector.LENS_FACING_BACK) - .build() - val cameraExecutor: ExecutorService = Executors.newSingleThreadExecutor() - cameraProviderFuture?.addListener({ - preview = Preview.Builder().build().also { - it.setSurfaceProvider(previewView.surfaceProvider) - } - val detector: QrCodeDetector<GrayU8> = FactoryFiducial.qrcode(null, GrayU8::class.java) - fun getQR(imageProxy: ImageProxy) { - val currentTimeStamp = System.currentTimeMillis() - if (currentTimeStamp - lastAnalyzedTimeStamp >= TimeUnit.SECONDS.toMillis(1)) { - detector.process(imageProxyToGrayU8(imageProxy)) - val found = detector.detections - val qr = found.firstOrNull() - if (qr != null) { - if (qr.message != contactLink) { - // Make sure link is new and not a repeat - contactLink = qr.message - onBarcode(contactLink) + Box(Modifier.fillMaxWidth(), contentAlignment = Alignment.Center) { + val cameraPermissionState = rememberPermissionState(permission = Manifest.permission.CAMERA) + val modifier = Modifier + .padding(padding) + .clipToBounds() + .widthIn(max = 400.dp) + .aspectRatio(1f) + val showScanner = remember { showQRCodeScanner } + if (showScanner.value && cameraPermissionState.hasPermission) { + AndroidView( + factory = { AndroidViewContext -> + PreviewView(AndroidViewContext).apply { + this.scaleType = PreviewView.ScaleType.FILL_CENTER + layoutParams = ViewGroup.LayoutParams( + ViewGroup.LayoutParams.MATCH_PARENT, + ViewGroup.LayoutParams.MATCH_PARENT, + ) + implementationMode = PreviewView.ImplementationMode.COMPATIBLE + } + }, + modifier = modifier + ) { previewView -> + val cameraSelector: CameraSelector = CameraSelector.Builder() + .requireLensFacing(CameraSelector.LENS_FACING_BACK) + .build() + val cameraExecutor: ExecutorService = Executors.newSingleThreadExecutor() + cameraProviderFuture?.addListener({ + preview = Preview.Builder().build().also { + it.setSurfaceProvider(previewView.surfaceProvider) + } + val detector: QrCodeDetector<GrayU8> = FactoryFiducial.qrcode(null, GrayU8::class.java) + fun getQR(imageProxy: ImageProxy) { + val currentTimeStamp = System.currentTimeMillis() + if (currentTimeStamp - lastAnalyzedTimeStamp >= TimeUnit.SECONDS.toMillis(1)) { + detector.process(imageProxyToGrayU8(imageProxy)) + val found = detector.detections + val qr = found.firstOrNull() + if (qr != null) { + if (qr.message != contactLink) { + // Make sure link is new and not a repeat + contactLink = qr.message + onBarcode(contactLink) + } + } } + imageProxy.close() + } + + val imageAnalyzer = ImageAnalysis.Analyzer { proxy -> getQR(proxy) } + val imageAnalysis: ImageAnalysis = ImageAnalysis.Builder() + .setBackpressureStrategy(ImageAnalysis.STRATEGY_KEEP_ONLY_LATEST) + .setImageQueueDepth(1) + .build() + .also { it.setAnalyzer(cameraExecutor, imageAnalyzer) } + try { + cameraProviderFuture?.get()?.unbindAll() + cameraProviderFuture?.get()?.bindToLifecycle(lifecycleOwner, cameraSelector, preview, imageAnalysis) + } catch (e: Exception) { + Log.d(TAG, "CameraPreview: ${e.localizedMessage}") + } + }, ContextCompat.getMainExecutor(context)) + } + } else { + val buttonColors = ButtonDefaults.buttonColors( + backgroundColor = MaterialTheme.colors.background.mixWith(MaterialTheme.colors.onBackground, 0.9f), + contentColor = MaterialTheme.colors.primary, + disabledBackgroundColor = MaterialTheme.colors.background.mixWith(MaterialTheme.colors.onBackground, 0.9f), + disabledContentColor = MaterialTheme.colors.primary, + ) + when { + !cameraPermissionState.hasPermission && !cameraPermissionState.permissionRequested && showScanner.value -> { + LaunchedEffect(Unit) { + cameraPermissionState.launchPermissionRequest() + } + } + !cameraPermissionState.hasPermission -> { + Button({ cameraPermissionState.launchPermissionRequest() }, modifier = modifier, colors = buttonColors) { + Icon(painterResource(MR.images.ic_camera_enhance), null) + Spacer(Modifier.width(DEFAULT_PADDING_HALF)) + Text(stringResource(MR.strings.enable_camera_access)) + } + } + cameraPermissionState.hasPermission -> { + Button({ showQRCodeScanner.value = true }, modifier = modifier, colors = buttonColors) { + Icon(painterResource(MR.images.ic_qr_code), null) + Spacer(Modifier.width(DEFAULT_PADDING_HALF)) + Text(stringResource(MR.strings.tap_to_scan)) + } + } + !LocalContext.current.packageManager.hasSystemFeature(PackageManager.FEATURE_CAMERA_ANY) -> { + Button({ }, enabled = false, modifier = modifier, colors = buttonColors) { + Text(stringResource(MR.strings.camera_not_available)) } } - imageProxy.close() } - val imageAnalyzer = ImageAnalysis.Analyzer { proxy -> getQR(proxy) } - val imageAnalysis: ImageAnalysis = ImageAnalysis.Builder() - .setBackpressureStrategy(ImageAnalysis.STRATEGY_KEEP_ONLY_LATEST) - .setImageQueueDepth(1) - .build() - .also { it.setAnalyzer(cameraExecutor, imageAnalyzer) } - try { - cameraProviderFuture?.get()?.unbindAll() - cameraProviderFuture?.get()?.bindToLifecycle(lifecycleOwner, cameraSelector, preview, imageAnalysis) - } catch (e: Exception) { - Log.d(TAG, "CameraPreview: ${e.localizedMessage}") - } - }, ContextCompat.getMainExecutor(context)) + } } } diff --git a/apps/multiplatform/common/src/androidMain/kotlin/chat/simplex/common/views/newchat/ScanToConnectView.android.kt b/apps/multiplatform/common/src/androidMain/kotlin/chat/simplex/common/views/newchat/ScanToConnectView.android.kt deleted file mode 100644 index f046f44bee..0000000000 --- a/apps/multiplatform/common/src/androidMain/kotlin/chat/simplex/common/views/newchat/ScanToConnectView.android.kt +++ /dev/null @@ -1,22 +0,0 @@ -package chat.simplex.common.views.newchat - -import android.Manifest -import androidx.compose.runtime.Composable -import androidx.compose.runtime.LaunchedEffect -import chat.simplex.common.model.ChatModel -import chat.simplex.common.model.RemoteHostInfo -import com.google.accompanist.permissions.rememberPermissionState - -@Composable -actual fun ScanToConnectView(chatModel: ChatModel, rh: RemoteHostInfo?, close: () -> Unit) { - val cameraPermissionState = rememberPermissionState(permission = Manifest.permission.CAMERA) - LaunchedEffect(Unit) { - cameraPermissionState.launchPermissionRequest() - } - ConnectContactLayout( - chatModel = chatModel, - rh = rh, - incognitoPref = chatModel.controller.appPrefs.incognito, - close = close - ) -} diff --git a/apps/multiplatform/common/src/androidMain/kotlin/chat/simplex/common/views/usersettings/SettingsView.android.kt b/apps/multiplatform/common/src/androidMain/kotlin/chat/simplex/common/views/usersettings/SettingsView.android.kt index 9b376bb9d3..f2c3d86ab5 100644 --- a/apps/multiplatform/common/src/androidMain/kotlin/chat/simplex/common/views/usersettings/SettingsView.android.kt +++ b/apps/multiplatform/common/src/androidMain/kotlin/chat/simplex/common/views/usersettings/SettingsView.android.kt @@ -5,8 +5,7 @@ import androidx.compose.runtime.Composable import androidx.work.WorkManager import chat.simplex.common.model.ChatModel import chat.simplex.common.platform.* -import chat.simplex.common.views.helpers.AlertManager -import chat.simplex.common.views.helpers.generalGetString +import chat.simplex.common.views.helpers.* import chat.simplex.res.MR import com.jakewharton.processphoenix.ProcessPhoenix import dev.icerock.moko.resources.compose.painterResource @@ -15,7 +14,7 @@ import dev.icerock.moko.resources.compose.stringResource @Composable actual fun SettingsSectionApp( showSettingsModal: (@Composable (ChatModel) -> Unit) -> (() -> Unit), - showCustomModal: (@Composable (ChatModel, () -> Unit) -> Unit) -> (() -> Unit), + showCustomModal: (@Composable ModalData.(ChatModel, () -> Unit) -> Unit) -> (() -> Unit), showVersion: () -> Unit, withAuth: (title: String, desc: String, block: () -> Unit) -> Unit ) { diff --git a/apps/multiplatform/common/src/commonMain/cpp/android/simplex-api.c b/apps/multiplatform/common/src/commonMain/cpp/android/simplex-api.c index 676c58fb49..5936bd5ff2 100644 --- a/apps/multiplatform/common/src/commonMain/cpp/android/simplex-api.c +++ b/apps/multiplatform/common/src/commonMain/cpp/android/simplex-api.c @@ -57,6 +57,7 @@ typedef long* chat_ctrl; */ extern char *chat_migrate_init(const char *path, const char *key, const char *confirm, chat_ctrl *ctrl); +extern char *chat_close_store(chat_ctrl ctrl); extern char *chat_send_cmd(chat_ctrl ctrl, const char *cmd); extern char *chat_send_remote_cmd(chat_ctrl ctrl, const int rhId, const char *cmd); extern char *chat_recv_msg(chat_ctrl ctrl); // deprecated @@ -93,6 +94,12 @@ Java_chat_simplex_common_platform_CoreKt_chatMigrateInit(JNIEnv *env, __unused j return ret; } +JNIEXPORT jstring JNICALL +Java_chat_simplex_common_platform_CoreKt_chatCloseStore(JNIEnv *env, __unused jclass clazz, jlong controller) { + jstring res = (*env)->NewStringUTF(env, chat_close_store((void*)controller)); + return res; +} + JNIEXPORT jstring JNICALL Java_chat_simplex_common_platform_CoreKt_chatSendCmd(JNIEnv *env, __unused jclass clazz, jlong controller, jstring msg) { const char *_msg = (*env)->GetStringUTFChars(env, msg, JNI_FALSE); diff --git a/apps/multiplatform/common/src/commonMain/cpp/desktop/simplex-api.c b/apps/multiplatform/common/src/commonMain/cpp/desktop/simplex-api.c index 292715bdc5..f15689285a 100644 --- a/apps/multiplatform/common/src/commonMain/cpp/desktop/simplex-api.c +++ b/apps/multiplatform/common/src/commonMain/cpp/desktop/simplex-api.c @@ -30,6 +30,7 @@ typedef long* chat_ctrl; */ extern char *chat_migrate_init(const char *path, const char *key, const char *confirm, chat_ctrl *ctrl); +extern char *chat_close_store(chat_ctrl ctrl); extern char *chat_send_cmd(chat_ctrl ctrl, const char *cmd); extern char *chat_send_remote_cmd(chat_ctrl ctrl, const int rhId, const char *cmd); extern char *chat_recv_msg(chat_ctrl ctrl); // deprecated @@ -106,6 +107,12 @@ Java_chat_simplex_common_platform_CoreKt_chatMigrateInit(JNIEnv *env, jclass cla return ret; } +JNIEXPORT jstring JNICALL +Java_chat_simplex_common_platform_CoreKt_chatCloseStore(JNIEnv *env, jclass clazz, jlong controller) { + jstring res = decode_to_utf8_string(env, chat_close_store((void*)controller)); + return res; +} + JNIEXPORT jstring JNICALL Java_chat_simplex_common_platform_CoreKt_chatSendCmd(JNIEnv *env, jclass clazz, jlong controller, jstring msg) { const char *_msg = encode_to_utf8_chars(env, msg); diff --git a/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/App.kt b/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/App.kt index d457eb57a1..bfff3bf9fb 100644 --- a/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/App.kt +++ b/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/App.kt @@ -44,7 +44,7 @@ data class SettingsViewState( fun AppScreen() { SimpleXTheme { ProvideWindowInsets(windowInsetsAnimationsEnabled = true) { - Surface(color = MaterialTheme.colors.background) { + Surface(color = MaterialTheme.colors.background, contentColor = LocalContentColor.current) { MainScreen() } } @@ -66,7 +66,7 @@ fun MainScreen() { !chatModel.controller.appPrefs.laNoticeShown.get() && showAdvertiseLAAlert && chatModel.controller.appPrefs.onboardingStage.get() == OnboardingStage.OnboardingComplete - && chatModel.chats.count() > 1 + && chatModel.chats.size > 2 && chatModel.activeCallInvitation.value == null ) { AppLock.showLANotice(ChatModel.controller.appPrefs.laNoticeShown) } @@ -85,7 +85,7 @@ fun MainScreen() { @Composable fun AuthView() { - Surface(color = MaterialTheme.colors.background) { + Surface(color = MaterialTheme.colors.background, contentColor = LocalContentColor.current) { Box( Modifier.fillMaxSize(), contentAlignment = Alignment.Center @@ -103,13 +103,15 @@ fun MainScreen() { } Box { + val unauthorized = remember { derivedStateOf { AppLock.userAuthorized.value != true } } val onboarding by remember { chatModel.controller.appPrefs.onboardingStage.state } val localUserCreated = chatModel.localUserCreated.value var showInitializationView by remember { mutableStateOf(false) } when { - chatModel.chatDbStatus.value == null && showInitializationView -> InitializationView() + chatModel.chatDbStatus.value == null && showInitializationView -> DefaultProgressView(stringResource(MR.strings.opening_database)) showChatDatabaseError -> { - chatModel.chatDbStatus.value?.let { + // Prevent showing keyboard on Android when: passcode enabled and database password not saved + if (!unauthorized.value && chatModel.chatDbStatus.value != null) { DatabaseErrorView(chatModel.chatDbStatus, chatModel.controller.appPrefs) } } @@ -125,6 +127,7 @@ fun MainScreen() { } val scaffoldState = rememberScaffoldState() val settingsState = remember { SettingsViewState(userPickerState, scaffoldState) } + SetupClipboardListener() if (appPlatform.isAndroid) { AndroidScreen(settingsState) } else { @@ -149,7 +152,6 @@ fun MainScreen() { SwitchingUsersView() } - val unauthorized = remember { derivedStateOf { AppLock.userAuthorized.value != true } } if (unauthorized.value && !(chatModel.activeCallViewIsVisible.value && chatModel.showCallView.value)) { LaunchedEffect(Unit) { // With these constrains when user presses back button while on ChatList, activity destroys and shows auth request @@ -342,22 +344,6 @@ fun DesktopScreen(settingsState: SettingsViewState) { } } -@Composable -fun InitializationView() { - Box(Modifier.fillMaxSize(), contentAlignment = Alignment.Center) { - Column(horizontalAlignment = Alignment.CenterHorizontally) { - CircularProgressIndicator( - Modifier - .padding(bottom = DEFAULT_PADDING) - .size(30.dp), - color = MaterialTheme.colors.secondary, - strokeWidth = 2.5.dp - ) - Text(stringResource(MR.strings.opening_database)) - } - } -} - @Composable private fun SwitchingUsersView() { if (remember { chatModel.switchingUsersAndHosts }.value) { diff --git a/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/AppLock.kt b/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/AppLock.kt index a1d4c0c62a..d6214c252c 100644 --- a/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/AppLock.kt +++ b/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/AppLock.kt @@ -1,8 +1,7 @@ package chat.simplex.common import androidx.compose.foundation.layout.fillMaxSize -import androidx.compose.material.MaterialTheme -import androidx.compose.material.Surface +import androidx.compose.material.* import androidx.compose.runtime.mutableStateOf import androidx.compose.ui.Modifier import chat.simplex.common.model.* @@ -107,7 +106,7 @@ object AppLock { private fun setPasscode() { val appPrefs = ChatController.appPrefs ModalManager.fullscreen.showCustomModal { close -> - Surface(Modifier.fillMaxSize(), color = MaterialTheme.colors.background) { + Surface(Modifier.fillMaxSize(), color = MaterialTheme.colors.background, contentColor = LocalContentColor.current) { SetAppPasscodeView( submit = { ChatModel.performLA.value = true diff --git a/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/model/ChatModel.kt b/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/model/ChatModel.kt index 5f1cf5783c..d44c80e92b 100644 --- a/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/model/ChatModel.kt +++ b/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/model/ChatModel.kt @@ -47,6 +47,7 @@ object ChatModel { val chatDbChanged = mutableStateOf<Boolean>(false) val chatDbEncrypted = mutableStateOf<Boolean?>(false) val chatDbStatus = mutableStateOf<DBMigrationResult?>(null) + val ctrlInitInProgress = mutableStateOf(false) val chats = mutableStateListOf<Chat>() // map of connections network statuses, key is agent connection id val networkStatuses = mutableStateMapOf<String, NetworkStatus>() @@ -55,6 +56,8 @@ object ChatModel { // current chat val chatId = mutableStateOf<String?>(null) val chatItems = mutableStateListOf<ChatItem>() + // rhId, chatId + val deletedChats = mutableStateOf<List<Pair<Long?, String>>>(emptyList()) val chatItemStatuses = mutableMapOf<Long, CIStatus>() val groupMembers = mutableStateListOf<GroupMember>() @@ -97,8 +100,8 @@ object ChatModel { val showCallView = mutableStateOf(false) val switchingCall = mutableStateOf(false) - // currently showing QR code - val connReqInv = mutableStateOf(null as String?) + // currently showing invitation + val showingInvitation = mutableStateOf(null as ShowingInvitation?) var draft = mutableStateOf(null as ComposeState?) var draftChatId = mutableStateOf(null as String?) @@ -109,7 +112,10 @@ object ChatModel { val filesToDelete = mutableSetOf<File>() val simplexLinkMode by lazy { mutableStateOf(ChatController.appPrefs.simplexLinkMode.get()) } - var updatingChatsMutex: Mutex = Mutex() + val clipboardHasText = mutableStateOf(false) + + val updatingChatsMutex: Mutex = Mutex() + val changingActiveUserMutex: Mutex = Mutex() val desktopNoUserNoRemote: Boolean @Composable get() = appPlatform.isDesktop && currentUser.value == null && currentRemoteHost.value == null fun desktopNoUserNoRemote(): Boolean = appPlatform.isDesktop && currentUser.value == null && currentRemoteHost.value == null @@ -146,7 +152,7 @@ object ChatModel { fun removeUser(user: User) { val i = getUserIndex(user) - if (i != -1 && users[i].user.userId != currentUser.value?.userId) { + if (i != -1) { users.removeAt(i) } } @@ -564,15 +570,30 @@ object ChatModel { chats.add(index = 0, chat) } - fun dismissConnReqView(id: String) { - if (connReqInv.value == null) return - val info = getChat(id)?.chatInfo as? ChatInfo.ContactConnection ?: return - if (info.contactConnection.connReqInv == connReqInv.value) { - connReqInv.value = null - ModalManager.center.closeModals() + fun replaceConnReqView(id: String, withId: String) { + if (id == showingInvitation.value?.connId) { + showingInvitation.value = null + chatModel.chatItems.clear() + chatModel.chatId.value = withId + ModalManager.end.closeModals() } } + fun dismissConnReqView(id: String) { + if (id == showingInvitation.value?.connId) { + showingInvitation.value = null + chatModel.chatItems.clear() + chatModel.chatId.value = null + // Close NewChatView + ModalManager.center.closeModals() + ModalManager.end.closeModals() + } + } + + fun markShowingInvitationUsed() { + showingInvitation.value = showingInvitation.value?.copy(connChatUsed = true) + } + fun removeChat(rhId: Long?, id: String) { chats.removeAll { it.id == id && it.remoteHostId == rhId } } @@ -633,9 +654,16 @@ object ChatModel { fun connectedToRemote(): Boolean = currentRemoteHost.value != null || remoteCtrlSession.value?.active == true } +data class ShowingInvitation( + val connId: String, + val connReq: String, + val connChatUsed: Boolean +) + enum class ChatType(val type: String) { Direct("@"), Group("#"), + Local("*"), ContactRequest("<@"), ContactConnection(":"); } @@ -755,6 +783,7 @@ data class Chat( get() = when (chatInfo) { is ChatInfo.Direct -> true is ChatInfo.Group -> chatInfo.groupInfo.membership.memberRole >= GroupMemberRole.Member + is ChatInfo.Local -> true else -> false } @@ -837,6 +866,30 @@ sealed class ChatInfo: SomeChat, NamedChat { } } + @Serializable @SerialName("local") + data class Local(val noteFolder: NoteFolder): ChatInfo() { + override val chatType get() = ChatType.Local + override val localDisplayName get() = noteFolder.localDisplayName + override val id get() = noteFolder.id + override val apiId get() = noteFolder.apiId + override val ready get() = noteFolder.ready + override val sendMsgEnabled get() = noteFolder.sendMsgEnabled + override val ntfsEnabled get() = noteFolder.ntfsEnabled + override val incognito get() = noteFolder.incognito + override fun featureEnabled(feature: ChatFeature) = noteFolder.featureEnabled(feature) + override val timedMessagesTTL: Int? get() = noteFolder.timedMessagesTTL + override val createdAt get() = noteFolder.createdAt + override val updatedAt get() = noteFolder.updatedAt + override val displayName get() = noteFolder.displayName + override val fullName get() = noteFolder.fullName + override val image get() = noteFolder.image + override val localAlias get() = noteFolder.localAlias + + companion object { + val sampleData = Local(NoteFolder.sampleData) + } + } + @Serializable @SerialName("contactRequest") class ContactRequest(val contactRequest: UserContactRequest): ChatInfo() { override val chatType get() = ChatType.ContactRequest @@ -1130,7 +1183,6 @@ data class LocalProfile( @Serializable data class UserProfileUpdateSummary( - val notChanged: Int, val updateSuccesses: Int, val updateFailures: Int, val changedContacts: List<Contact> @@ -1227,6 +1279,7 @@ data class GroupMember ( val memberCategory: GroupMemberCategory, val memberStatus: GroupMemberStatus, val memberSettings: GroupMemberSettings, + val blockedByAdmin: Boolean, val invitedBy: InvitedBy, val localDisplayName: String, val memberProfile: LocalProfile, @@ -1235,19 +1288,37 @@ data class GroupMember ( var activeConn: Connection? = null ) { val id: String get() = "#$groupId @$groupMemberId" - val displayName: String get() = memberProfile.localAlias.ifEmpty { memberProfile.displayName } + val displayName: String + get() { + val p = memberProfile + val name = p.localAlias.ifEmpty { p.displayName } + return pastMember(name) + } val fullName: String get() = memberProfile.fullName val image: String? get() = memberProfile.image val contactLink: String? = memberProfile.contactLink val verified get() = activeConn?.connectionCode != null + val blocked get() = blockedByAdmin || !memberSettings.showMessages val chatViewName: String - get() = memberProfile.localAlias.ifEmpty { displayName + (if (fullName == "" || fullName == displayName) "" else " / $fullName") } + get() { + val p = memberProfile + val name = p.localAlias.ifEmpty { p.displayName + (if (p.fullName == "" || p.fullName == p.displayName) "" else " / ${p.fullName}") } + return pastMember(name) + } + + private fun pastMember(name: String): String { + return if (memberStatus == GroupMemberStatus.MemUnknown) + String.format(generalGetString(MR.strings.past_member_vName), name) + else + name + } val memberActive: Boolean get() = when (this.memberStatus) { GroupMemberStatus.MemRemoved -> false GroupMemberStatus.MemLeft -> false GroupMemberStatus.MemGroupDeleted -> false + GroupMemberStatus.MemUnknown -> false GroupMemberStatus.MemInvited -> false GroupMemberStatus.MemIntroduced -> false GroupMemberStatus.MemIntroInvited -> false @@ -1262,6 +1333,7 @@ data class GroupMember ( GroupMemberStatus.MemRemoved -> false GroupMemberStatus.MemLeft -> false GroupMemberStatus.MemGroupDeleted -> false + GroupMemberStatus.MemUnknown -> false GroupMemberStatus.MemInvited -> false GroupMemberStatus.MemIntroduced -> true GroupMemberStatus.MemIntroInvited -> true @@ -1275,7 +1347,7 @@ data class GroupMember ( fun canBeRemoved(groupInfo: GroupInfo): Boolean { val userRole = groupInfo.membership.memberRole return memberStatus != GroupMemberStatus.MemRemoved && memberStatus != GroupMemberStatus.MemLeft - && userRole >= GroupMemberRole.Admin && userRole >= memberRole && groupInfo.membership.memberCurrent + && userRole >= GroupMemberRole.Admin && userRole >= memberRole && groupInfo.membership.memberActive } fun canChangeRoleTo(groupInfo: GroupInfo): List<GroupMemberRole>? = @@ -1284,6 +1356,12 @@ data class GroupMember ( GroupMemberRole.values().filter { it <= userRole && it != GroupMemberRole.Author } } + fun canBlockForAll(groupInfo: GroupInfo): Boolean { + val userRole = groupInfo.membership.memberRole + return memberStatus != GroupMemberStatus.MemRemoved && memberStatus != GroupMemberStatus.MemLeft && memberRole < GroupMemberRole.Admin + && userRole >= GroupMemberRole.Admin && userRole >= memberRole && groupInfo.membership.memberActive + } + val memberIncognito = memberProfile.profileId != memberContactProfileId companion object { @@ -1295,6 +1373,7 @@ data class GroupMember ( memberCategory = GroupMemberCategory.InviteeMember, memberStatus = GroupMemberStatus.MemComplete, memberSettings = GroupMemberSettings(showMessages = true), + blockedByAdmin = false, invitedBy = InvitedBy.IBUser(), localDisplayName = "alice", memberProfile = LocalProfile.sampleData, @@ -1351,6 +1430,7 @@ enum class GroupMemberStatus { @SerialName("removed") MemRemoved, @SerialName("left") MemLeft, @SerialName("deleted") MemGroupDeleted, + @SerialName("unknown") MemUnknown, @SerialName("invited") MemInvited, @SerialName("introduced") MemIntroduced, @SerialName("intro-inv") MemIntroInvited, @@ -1364,6 +1444,7 @@ enum class GroupMemberStatus { MemRemoved -> generalGetString(MR.strings.group_member_status_removed) MemLeft -> generalGetString(MR.strings.group_member_status_left) MemGroupDeleted -> generalGetString(MR.strings.group_member_status_group_deleted) + MemUnknown -> generalGetString(MR.strings.group_member_status_unknown) MemInvited -> generalGetString(MR.strings.group_member_status_invited) MemIntroduced -> generalGetString(MR.strings.group_member_status_introduced) MemIntroInvited -> generalGetString(MR.strings.group_member_status_intro_invitation) @@ -1378,6 +1459,7 @@ enum class GroupMemberStatus { MemRemoved -> generalGetString(MR.strings.group_member_status_removed) MemLeft -> generalGetString(MR.strings.group_member_status_left) MemGroupDeleted -> generalGetString(MR.strings.group_member_status_group_deleted) + MemUnknown -> generalGetString(MR.strings.group_member_status_unknown_short) MemInvited -> generalGetString(MR.strings.group_member_status_invited) MemIntroduced -> generalGetString(MR.strings.group_member_status_connecting) MemIntroInvited -> generalGetString(MR.strings.group_member_status_connecting) @@ -1419,6 +1501,40 @@ class MemberSubError ( val memberError: ChatError ) +@Serializable +class NoteFolder( + val noteFolderId: Long, + val favorite: Boolean, + val unread: Boolean, + override val createdAt: Instant, + override val updatedAt: Instant +): SomeChat, NamedChat { + override val chatType get() = ChatType.Local + override val id get() = "*$noteFolderId" + override val apiId get() = noteFolderId + override val ready get() = true + override val sendMsgEnabled get() = true + override val ntfsEnabled get() = false + override val incognito get() = false + override fun featureEnabled(feature: ChatFeature) = feature == ChatFeature.Voice + override val timedMessagesTTL: Int? get() = null + override val displayName get() = generalGetString(MR.strings.note_folder_local_display_name) + override val fullName get() = "" + override val image get() = null + override val localAlias get() = "" + override val localDisplayName: String get() = "" + + companion object { + val sampleData = NoteFolder( + noteFolderId = 1, + favorite = false, + unread = false, + createdAt = Clock.System.now(), + updatedAt = Clock.System.now() + ) + } +} + @Serializable class UserContactRequest ( val contactRequestId: Long, @@ -1597,13 +1713,29 @@ data class ChatItem ( val encryptedFile: Boolean? = if (file?.fileSource == null) null else file.fileSource.cryptoArgs != null - val encryptLocalFile: Boolean - get() = content.msgContent !is MsgContent.MCVideo && - chatController.appPrefs.privacyEncryptLocalFiles.get() - val memberDisplayName: String? get() = - if (chatDir is CIDirection.GroupRcv) chatDir.groupMember.chatViewName - else null + when (chatDir) { + is CIDirection.GroupRcv -> when (content) { + is CIContent.RcvGroupEventContent -> when (val event = content.rcvGroupEvent) { + is RcvGroupEvent.MemberProfileUpdated -> { + val to = event.toProfile + val from = event.fromProfile + when { + to.displayName != from.displayName || to.fullName != from.fullName -> null + else -> chatDir.groupMember.chatViewName + } + } + + else -> chatDir.groupMember.chatViewName + } + + else -> chatDir.groupMember.chatViewName + } + + else -> null + } + + val localNote: Boolean = chatDir is CIDirection.LocalSnd || chatDir is CIDirection.LocalRcv val isDeletedContent: Boolean get() = when (content) { @@ -1611,6 +1743,7 @@ data class ChatItem ( is CIContent.RcvDeleted -> true is CIContent.SndModerated -> true is CIContent.RcvModerated -> true + is CIContent.RcvBlocked -> true else -> false } @@ -1662,47 +1795,51 @@ data class ChatItem ( } } - private val showNtfDir: Boolean get() = !chatDir.sent - val showNotification: Boolean get() = when (content) { - is CIContent.SndMsgContent -> showNtfDir - is CIContent.RcvMsgContent -> showNtfDir - is CIContent.SndDeleted -> showNtfDir - is CIContent.RcvDeleted -> showNtfDir - is CIContent.SndCall -> showNtfDir + is CIContent.SndMsgContent -> false + is CIContent.RcvMsgContent -> meta.itemDeleted == null + is CIContent.SndDeleted -> false + is CIContent.RcvDeleted -> false + is CIContent.SndCall -> false is CIContent.RcvCall -> false // notification is shown on CallInvitation instead - is CIContent.RcvIntegrityError -> showNtfDir - is CIContent.RcvDecryptionError -> showNtfDir - is CIContent.RcvGroupInvitation -> showNtfDir - is CIContent.SndGroupInvitation -> showNtfDir - is CIContent.RcvDirectEventContent -> false + is CIContent.RcvIntegrityError -> false + is CIContent.RcvDecryptionError -> false + is CIContent.RcvGroupInvitation -> true + is CIContent.SndGroupInvitation -> false + is CIContent.RcvDirectEventContent -> when (content.rcvDirectEvent) { + is RcvDirectEvent.ContactDeleted -> false + is RcvDirectEvent.ProfileUpdated -> true + } is CIContent.RcvGroupEventContent -> when (content.rcvGroupEvent) { is RcvGroupEvent.MemberAdded -> false is RcvGroupEvent.MemberConnected -> false is RcvGroupEvent.MemberLeft -> false is RcvGroupEvent.MemberRole -> false - is RcvGroupEvent.UserRole -> showNtfDir + is RcvGroupEvent.MemberBlocked -> false + is RcvGroupEvent.UserRole -> true is RcvGroupEvent.MemberDeleted -> false - is RcvGroupEvent.UserDeleted -> showNtfDir - is RcvGroupEvent.GroupDeleted -> showNtfDir + is RcvGroupEvent.UserDeleted -> true + is RcvGroupEvent.GroupDeleted -> true is RcvGroupEvent.GroupUpdated -> false is RcvGroupEvent.InvitedViaGroupLink -> false is RcvGroupEvent.MemberCreatedContact -> false + is RcvGroupEvent.MemberProfileUpdated -> false } - is CIContent.SndGroupEventContent -> showNtfDir + is CIContent.SndGroupEventContent -> false is CIContent.RcvConnEventContent -> false - is CIContent.SndConnEventContent -> showNtfDir + is CIContent.SndConnEventContent -> false is CIContent.RcvChatFeature -> false - is CIContent.SndChatFeature -> showNtfDir + is CIContent.SndChatFeature -> false is CIContent.RcvChatPreference -> false - is CIContent.SndChatPreference -> showNtfDir + is CIContent.SndChatPreference -> false is CIContent.RcvGroupFeature -> false - is CIContent.SndGroupFeature -> showNtfDir - is CIContent.RcvChatFeatureRejected -> showNtfDir - is CIContent.RcvGroupFeatureRejected -> showNtfDir - is CIContent.SndModerated -> true - is CIContent.RcvModerated -> true + is CIContent.SndGroupFeature -> false + is CIContent.RcvChatFeatureRejected -> true + is CIContent.RcvGroupFeatureRejected -> false + is CIContent.SndModerated -> false + is CIContent.RcvModerated -> false + is CIContent.RcvBlocked -> false is CIContent.InvalidJSON -> false } @@ -1868,12 +2005,16 @@ sealed class CIDirection { @Serializable @SerialName("directRcv") class DirectRcv: CIDirection() @Serializable @SerialName("groupSnd") class GroupSnd: CIDirection() @Serializable @SerialName("groupRcv") class GroupRcv(val groupMember: GroupMember): CIDirection() + @Serializable @SerialName("localSnd") class LocalSnd: CIDirection() + @Serializable @SerialName("localRcv") class LocalRcv: CIDirection() val sent: Boolean get() = when(this) { is DirectSnd -> true is DirectRcv -> false is GroupSnd -> true is GroupRcv -> false + is LocalSnd -> true + is LocalRcv -> false } } @@ -2043,6 +2184,7 @@ enum class SndCIStatusProgress { sealed class CIDeleted { @Serializable @SerialName("deleted") class Deleted(val deletedTs: Instant?): CIDeleted() @Serializable @SerialName("blocked") class Blocked(val deletedTs: Instant?): CIDeleted() + @Serializable @SerialName("blockedByAdmin") class BlockedByAdmin(val deletedTs: Instant?): CIDeleted() @Serializable @SerialName("moderated") class Moderated(val deletedTs: Instant?, val byGroupMember: GroupMember): CIDeleted() } @@ -2087,6 +2229,7 @@ sealed class CIContent: ItemContent { @Serializable @SerialName("rcvGroupFeatureRejected") class RcvGroupFeatureRejected(val groupFeature: GroupFeature): CIContent() { override val msgContent: MsgContent? get() = null } @Serializable @SerialName("sndModerated") object SndModerated: CIContent() { override val msgContent: MsgContent? get() = null } @Serializable @SerialName("rcvModerated") object RcvModerated: CIContent() { override val msgContent: MsgContent? get() = null } + @Serializable @SerialName("rcvBlocked") object RcvBlocked: CIContent() { override val msgContent: MsgContent? get() = null } @Serializable @SerialName("invalidJSON") data class InvalidJSON(val json: String): CIContent() { override val msgContent: MsgContent? get() = null } override val text: String get() = when (this) { @@ -2115,6 +2258,7 @@ sealed class CIContent: ItemContent { is RcvGroupFeatureRejected -> "${groupFeature.text}: ${generalGetString(MR.strings.feature_received_prohibited)}" is SndModerated -> generalGetString(MR.strings.moderated_description) is RcvModerated -> generalGetString(MR.strings.moderated_description) + is RcvBlocked -> generalGetString(MR.strings.blocked_by_admin_item_description) is InvalidJSON -> "invalid data" } @@ -2127,6 +2271,7 @@ sealed class CIContent: ItemContent { is RcvDecryptionError -> true is RcvGroupInvitation -> true is RcvModerated -> true + is RcvBlocked -> true is InvalidJSON -> true else -> false } @@ -2189,6 +2334,8 @@ class CIQuote ( is CIDirection.DirectRcv -> null is CIDirection.GroupSnd -> membership?.displayName ?: generalGetString(MR.strings.sender_you_pronoun) is CIDirection.GroupRcv -> chatDir.groupMember.displayName + is CIDirection.LocalSnd -> generalGetString(MR.strings.sender_you_pronoun) + is CIDirection.LocalRcv -> null null -> null } @@ -2385,10 +2532,36 @@ data class CryptoFile( tmpFile?.delete() } + private fun decryptToTmpFile(): URI? { + val absoluteFilePath = if (isAbsolutePath) filePath else getAppFilePath(filePath) + val tmpFile = createTmpFileIfNeeded() + decryptCryptoFile(absoluteFilePath, cryptoArgs ?: return null, tmpFile.absolutePath) + return tmpFile.toURI() + } + + fun decryptedGet(): URI? { + val decrypted = decryptedUris[filePath] + return if (decrypted != null && decrypted.toFile().exists()) { + decrypted + } else { + null + } + } + + fun decryptedGetOrCreate(): URI? { + val decrypted = decryptedGet() ?: decryptToTmpFile() + if (decrypted != null) { + decryptedUris[filePath] = decrypted + } + return decrypted + } + companion object { fun plain(f: String): CryptoFile = CryptoFile(f, null) fun desktopPlain(f: URI): CryptoFile = CryptoFile(f.toFile().absolutePath, null) + + private val decryptedUris = mutableMapOf<String, URI>() } } @@ -2434,7 +2607,8 @@ private val rcvCancelAction: CancelAction = CancelAction( @Serializable enum class FileProtocol { @SerialName("smp") SMP, - @SerialName("xftp") XFTP; + @SerialName("xftp") XFTP, + @SerialName("local") LOCAL; } @Serializable @@ -2667,6 +2841,8 @@ sealed class Format { is Phone -> linkStyle } + val isSimplexLink = this is SimplexLink + companion object { val linkStyle @Composable get() = SpanStyle(color = MaterialTheme.colors.primary, textDecoration = TextDecoration.Underline) } @@ -2764,10 +2940,30 @@ sealed class MsgErrorType() { @Serializable sealed class RcvDirectEvent() { @Serializable @SerialName("contactDeleted") class ContactDeleted(): RcvDirectEvent() + @Serializable @SerialName("profileUpdated") class ProfileUpdated(val fromProfile: Profile, val toProfile: Profile): RcvDirectEvent() val text: String get() = when (this) { is ContactDeleted -> generalGetString(MR.strings.rcv_direct_event_contact_deleted) + is ProfileUpdated -> profileUpdatedText(fromProfile, toProfile) } + + private fun profileUpdatedText(from: Profile, to: Profile): String = + when { + to.displayName != from.displayName || to.fullName != from.fullName -> + generalGetString(MR.strings.profile_update_event_contact_name_changed).format(from.profileViewName, to.profileViewName) + + to.image != from.image -> when (to.image) { + null -> generalGetString(MR.strings.profile_update_event_removed_picture) + else -> generalGetString(MR.strings.profile_update_event_set_new_picture) + } + + to.contactLink != from.contactLink -> when (to.contactLink) { + null -> generalGetString(MR.strings.profile_update_event_removed_address) + else -> generalGetString(MR.strings.profile_update_event_set_new_address) + } + // shouldn't happen if backend correctly creates item; UI should be synchronized with backend + else -> generalGetString(MR.strings.profile_update_event_updated_profile) + } } @Serializable @@ -2776,6 +2972,7 @@ sealed class RcvGroupEvent() { @Serializable @SerialName("memberConnected") class MemberConnected(): RcvGroupEvent() @Serializable @SerialName("memberLeft") class MemberLeft(): RcvGroupEvent() @Serializable @SerialName("memberRole") class MemberRole(val groupMemberId: Long, val profile: Profile, val role: GroupMemberRole): RcvGroupEvent() + @Serializable @SerialName("memberBlocked") class MemberBlocked(val groupMemberId: Long, val profile: Profile, val blocked: Boolean): RcvGroupEvent() @Serializable @SerialName("userRole") class UserRole(val role: GroupMemberRole): RcvGroupEvent() @Serializable @SerialName("memberDeleted") class MemberDeleted(val groupMemberId: Long, val profile: Profile): RcvGroupEvent() @Serializable @SerialName("userDeleted") class UserDeleted(): RcvGroupEvent() @@ -2783,12 +2980,18 @@ sealed class RcvGroupEvent() { @Serializable @SerialName("groupUpdated") class GroupUpdated(val groupProfile: GroupProfile): RcvGroupEvent() @Serializable @SerialName("invitedViaGroupLink") class InvitedViaGroupLink(): RcvGroupEvent() @Serializable @SerialName("memberCreatedContact") class MemberCreatedContact(): RcvGroupEvent() + @Serializable @SerialName("memberProfileUpdated") class MemberProfileUpdated(val fromProfile: Profile, val toProfile: Profile): RcvGroupEvent() val text: String get() = when (this) { is MemberAdded -> String.format(generalGetString(MR.strings.rcv_group_event_member_added), profile.profileViewName) is MemberConnected -> generalGetString(MR.strings.rcv_group_event_member_connected) is MemberLeft -> generalGetString(MR.strings.rcv_group_event_member_left) is MemberRole -> String.format(generalGetString(MR.strings.rcv_group_event_changed_member_role), profile.profileViewName, role.text) + is MemberBlocked -> if (blocked) { + String.format(generalGetString(MR.strings.rcv_group_event_member_blocked), profile.profileViewName) + } else { + String.format(generalGetString(MR.strings.rcv_group_event_member_unblocked), profile.profileViewName) + } is UserRole -> String.format(generalGetString(MR.strings.rcv_group_event_changed_your_role), role.text) is MemberDeleted -> String.format(generalGetString(MR.strings.rcv_group_event_member_deleted), profile.profileViewName) is UserDeleted -> generalGetString(MR.strings.rcv_group_event_user_deleted) @@ -2796,13 +2999,28 @@ sealed class RcvGroupEvent() { is GroupUpdated -> generalGetString(MR.strings.rcv_group_event_updated_group_profile) is InvitedViaGroupLink -> generalGetString(MR.strings.rcv_group_event_invited_via_your_group_link) is MemberCreatedContact -> generalGetString(MR.strings.rcv_group_event_member_created_contact) + is MemberProfileUpdated -> profileUpdatedText(fromProfile, toProfile) } + + private fun profileUpdatedText(from: Profile, to: Profile): String = + when { + to.displayName != from.displayName || to.fullName != from.fullName -> + generalGetString(MR.strings.profile_update_event_member_name_changed).format(from.profileViewName, to.profileViewName) + + to.image != from.image -> when (to.image) { + null -> generalGetString(MR.strings.profile_update_event_removed_picture) + else -> generalGetString(MR.strings.profile_update_event_set_new_picture) + } + // shouldn't happen if backend correctly creates item; UI should be synchronized with backend + else -> generalGetString(MR.strings.profile_update_event_updated_profile) + } } @Serializable sealed class SndGroupEvent() { @Serializable @SerialName("memberRole") class MemberRole(val groupMemberId: Long, val profile: Profile, val role: GroupMemberRole): SndGroupEvent() @Serializable @SerialName("userRole") class UserRole(val role: GroupMemberRole): SndGroupEvent() + @Serializable @SerialName("memberBlocked") class MemberBlocked(val groupMemberId: Long, val profile: Profile, val blocked: Boolean): SndGroupEvent() @Serializable @SerialName("memberDeleted") class MemberDeleted(val groupMemberId: Long, val profile: Profile): SndGroupEvent() @Serializable @SerialName("userLeft") class UserLeft(): SndGroupEvent() @Serializable @SerialName("groupUpdated") class GroupUpdated(val groupProfile: GroupProfile): SndGroupEvent() @@ -2810,6 +3028,11 @@ sealed class SndGroupEvent() { val text: String get() = when (this) { is MemberRole -> String.format(generalGetString(MR.strings.snd_group_event_changed_member_role), profile.profileViewName, role.text) is UserRole -> String.format(generalGetString(MR.strings.snd_group_event_changed_role_for_yourself), role.text) + is MemberBlocked -> if (blocked) { + String.format(generalGetString(MR.strings.snd_group_event_member_blocked), profile.profileViewName) + } else { + String.format(generalGetString(MR.strings.snd_group_event_member_unblocked), profile.profileViewName) + } is MemberDeleted -> String.format(generalGetString(MR.strings.snd_group_event_member_deleted), profile.profileViewName) is UserLeft -> generalGetString(MR.strings.snd_group_event_user_left) is GroupUpdated -> generalGetString(MR.strings.snd_group_event_group_profile_updated) diff --git a/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/model/SimpleXAPI.kt b/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/model/SimpleXAPI.kt index 012fce705f..ce65ec5121 100644 --- a/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/model/SimpleXAPI.kt +++ b/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/model/SimpleXAPI.kt @@ -5,11 +5,11 @@ import androidx.compose.runtime.* import androidx.compose.ui.graphics.Color import androidx.compose.ui.graphics.painter.Painter import chat.simplex.common.model.ChatModel.updatingChatsMutex +import chat.simplex.common.model.ChatModel.changingActiveUserMutex import dev.icerock.moko.resources.compose.painterResource import chat.simplex.common.platform.* import chat.simplex.common.ui.theme.* import chat.simplex.common.views.call.* -import chat.simplex.common.views.newchat.ConnectViaLinkTab import chat.simplex.common.views.onboarding.OnboardingStage import chat.simplex.common.views.usersettings.* import com.charleskorn.kaml.Yaml @@ -107,8 +107,10 @@ class AppPreferences { val chatArchiveName = mkStrPreference(SHARED_PREFS_CHAT_ARCHIVE_NAME, null) val chatArchiveTime = mkDatePreference(SHARED_PREFS_CHAT_ARCHIVE_TIME, null) val chatLastStart = mkDatePreference(SHARED_PREFS_CHAT_LAST_START, null) + val chatStopped = mkBoolPreference(SHARED_PREFS_CHAT_STOPPED, false) val developerTools = mkBoolPreference(SHARED_PREFS_DEVELOPER_TOOLS, false) val showInternalErrors = mkBoolPreference(SHARED_PREFS_SHOW_INTERNAL_ERRORS, false) + val showSlowApiCalls = mkBoolPreference(SHARED_PREFS_SHOW_SLOW_API_CALLS, false) val terminalAlwaysVisible = mkBoolPreference(SHARED_PREFS_TERMINAL_ALWAYS_VISIBLE, false) val networkUseSocksProxy = mkBoolPreference(SHARED_PREFS_NETWORK_USE_SOCKS_PROXY, false) val networkProxyHostPort = mkStrPreference(SHARED_PREFS_NETWORK_PROXY_HOST_PORT, "localhost:9050") @@ -136,7 +138,6 @@ class AppPreferences { val networkTCPKeepIntvl = mkIntPreference(SHARED_PREFS_NETWORK_TCP_KEEP_INTVL, KeepAliveOpts.defaults.keepIntvl) val networkTCPKeepCnt = mkIntPreference(SHARED_PREFS_NETWORK_TCP_KEEP_CNT, KeepAliveOpts.defaults.keepCnt) val incognito = mkBoolPreference(SHARED_PREFS_INCOGNITO, false) - val connectViaLinkTab = mkStrPreference(SHARED_PREFS_CONNECT_VIA_LINK_TAB, ConnectViaLinkTab.SCAN.name) val liveMessageAlertShown = mkBoolPreference(SHARED_PREFS_LIVE_MESSAGE_ALERT_SHOWN, false) val showHiddenProfilesNotice = mkBoolPreference(SHARED_PREFS_SHOW_HIDDEN_PROFILES_NOTICE, true) val showMuteProfileAlert = mkBoolPreference(SHARED_PREFS_SHOW_MUTE_PROFILE_ALERT, true) @@ -276,8 +277,10 @@ class AppPreferences { private const val SHARED_PREFS_APP_LANGUAGE = "AppLanguage" private const val SHARED_PREFS_ONBOARDING_STAGE = "OnboardingStage" private const val SHARED_PREFS_CHAT_LAST_START = "ChatLastStart" + private const val SHARED_PREFS_CHAT_STOPPED = "ChatStopped" private const val SHARED_PREFS_DEVELOPER_TOOLS = "DeveloperTools" private const val SHARED_PREFS_SHOW_INTERNAL_ERRORS = "ShowInternalErrors" + private const val SHARED_PREFS_SHOW_SLOW_API_CALLS = "ShowSlowApiCalls" private const val SHARED_PREFS_TERMINAL_ALWAYS_VISIBLE = "TerminalAlwaysVisible" private const val SHARED_PREFS_NETWORK_USE_SOCKS_PROXY = "NetworkUseSocksProxy" private const val SHARED_PREFS_NETWORK_PROXY_HOST_PORT = "NetworkProxyHostPort" @@ -294,7 +297,6 @@ class AppPreferences { private const val SHARED_PREFS_NETWORK_TCP_KEEP_INTVL = "NetworkTCPKeepIntvl" private const val SHARED_PREFS_NETWORK_TCP_KEEP_CNT = "NetworkTCPKeepCnt" private const val SHARED_PREFS_INCOGNITO = "Incognito" - private const val SHARED_PREFS_CONNECT_VIA_LINK_TAB = "ConnectViaLinkTab" private const val SHARED_PREFS_LIVE_MESSAGE_ALERT_SHOWN = "LiveMessageAlertShown" private const val SHARED_PREFS_SHOW_HIDDEN_PROFILES_NOTICE = "ShowHiddenProfilesNotice" private const val SHARED_PREFS_SHOW_MUTE_PROFILE_ALERT = "ShowMuteProfileAlert" @@ -336,29 +338,22 @@ object ChatController { var lastMsgReceivedTimestamp: Long = System.currentTimeMillis() private set - private fun currentUserId(funcName: String): Long { + private suspend fun currentUserId(funcName: String): Long = changingActiveUserMutex.withLock { val userId = chatModel.currentUser.value?.userId if (userId == null) { val error = "$funcName: no current user" Log.e(TAG, error) throw Exception(error) } - return userId + userId } suspend fun startChat(user: User) { Log.d(TAG, "user: $user") try { - if (chatModel.chatRunning.value == true) return apiSetNetworkConfig(getNetCfg()) - apiSetTempFolder(coreTmpDir.absolutePath) - apiSetFilesFolder(appFilesDir.absolutePath) - if (appPlatform.isDesktop) { - apiSetRemoteHostsFolder(remoteHostsDir.absolutePath) - } - apiSetXFTPConfig(getXFTPCfg()) - apiSetEncryptLocalFiles(appPrefs.privacyEncryptLocalFiles.get()) val justStarted = apiStartChat() + appPrefs.chatStopped.set(false) val users = listUsers(null) chatModel.users.clear() chatModel.users.addAll(users) @@ -370,6 +365,9 @@ object ChatController { chatModel.chatRunning.value = true startReceiver() setLocalDeviceName(appPrefs.deviceNameForRemoteAccess.get()!!) + if (appPreferences.onboardingStage.get() == OnboardingStage.OnboardingComplete && !chatModel.controller.appPrefs.privacyDeliveryReceiptsSet.get()) { + chatModel.setDeliveryReceipts.value = true + } Log.d(TAG, "startChat: started") } else { updatingChatsMutex.withLock { @@ -388,13 +386,6 @@ object ChatController { Log.d(TAG, "user: null") try { if (chatModel.chatRunning.value == true) return - apiSetTempFolder(coreTmpDir.absolutePath) - apiSetFilesFolder(appFilesDir.absolutePath) - if (appPlatform.isDesktop) { - apiSetRemoteHostsFolder(remoteHostsDir.absolutePath) - } - apiSetXFTPConfig(getXFTPCfg()) - apiSetEncryptLocalFiles(appPrefs.privacyEncryptLocalFiles.get()) chatModel.users.clear() chatModel.currentUser.value = null chatModel.localUserCreated.value = false @@ -418,15 +409,18 @@ object ChatController { } } - suspend fun changeActiveUser_(rhId: Long?, toUserId: Long, viewPwd: String?) { - val currentUser = apiSetActiveUser(rhId, toUserId, viewPwd) - chatModel.currentUser.value = currentUser + suspend fun changeActiveUser_(rhId: Long?, toUserId: Long?, viewPwd: String?) { + val currentUser = changingActiveUserMutex.withLock { + (if (toUserId != null) apiSetActiveUser(rhId, toUserId, viewPwd) else apiGetActiveUser(rhId)).also { + chatModel.currentUser.value = it + } + } val users = listUsers(rhId) chatModel.users.clear() chatModel.users.addAll(users) getUserChatData(rhId) val invitation = chatModel.callInvitations.values.firstOrNull { inv -> inv.user.userId == toUserId } - if (invitation != null) { + if (invitation != null && currentUser != null) { chatModel.callManager.reportNewIncomingCall(invitation.copy(user = currentUser)) } } @@ -517,6 +511,10 @@ object ChatController { r is CR.ChatCmdError && r.chatError is ChatError.ChatErrorChat && r.chatError.errorType is ChatErrorType.UserExists ) { AlertManager.shared.showAlertMsg(generalGetString(MR.strings.failed_to_create_user_duplicate_title), generalGetString(MR.strings.failed_to_create_user_duplicate_desc)) + } else if ( + r is CR.ChatCmdError && r.chatError is ChatError.ChatErrorChat && r.chatError.errorType is ChatErrorType.InvalidDisplayName + ) { + AlertManager.shared.showAlertMsg(generalGetString(MR.strings.failed_to_create_user_invalid_title), generalGetString(MR.strings.failed_to_create_user_invalid_desc)) } else { AlertManager.shared.showAlertMsg(generalGetString(MR.strings.failed_to_create_user_title), r.details) } @@ -601,19 +599,19 @@ object ChatController { } } - private suspend fun apiSetTempFolder(tempFolder: String) { + suspend fun apiSetTempFolder(tempFolder: String) { val r = sendCmd(null, CC.SetTempFolder(tempFolder)) if (r is CR.CmdOk) return throw Error("failed to set temp folder: ${r.responseType} ${r.details}") } - private suspend fun apiSetFilesFolder(filesFolder: String) { + suspend fun apiSetFilesFolder(filesFolder: String) { val r = sendCmd(null, CC.SetFilesFolder(filesFolder)) if (r is CR.CmdOk) return throw Error("failed to set files folder: ${r.responseType} ${r.details}") } - private suspend fun apiSetRemoteHostsFolder(remoteHostsFolder: String) { + suspend fun apiSetRemoteHostsFolder(remoteHostsFolder: String) { val r = sendCmd(null, CC.SetRemoteHostsFolder(remoteHostsFolder)) if (r is CR.CmdOk) return throw Error("failed to set remote hosts folder: ${r.responseType} ${r.details}") @@ -682,6 +680,17 @@ object ChatController { } } } + suspend fun apiCreateChatItem(rh: Long?, noteFolderId: Long, file: CryptoFile? = null, mc: MsgContent): AChatItem? { + val cmd = CC.ApiCreateChatItem(noteFolderId, file, mc) + val r = sendCmd(rh, cmd) + return when (r) { + is CR.NewChatItem -> r.chatItem + else -> { + apiErrorAlert("apiCreateChatItem", generalGetString(MR.strings.error_creating_message), r) + null + } + } + } suspend fun apiGetChatItemInfo(rh: Long?, type: ChatType, id: Long, itemId: Long): ChatItemInfo? { return when (val r = sendCmd(rh, CC.ApiGetChatItemInfo(type, id, itemId))) { @@ -892,19 +901,16 @@ object ChatController { - suspend fun apiAddContact(rh: Long?, incognito: Boolean): Pair<String, PendingContactConnection>? { - val userId = chatModel.currentUser.value?.userId ?: run { - Log.e(TAG, "apiAddContact: no current user") - return null - } + suspend fun apiAddContact(rh: Long?, incognito: Boolean): Pair<Pair<String, PendingContactConnection>?, (() -> Unit)?> { + val userId = try { currentUserId("apiAddContact") } catch (e: Exception) { return null to null } val r = sendCmd(rh, CC.APIAddContact(userId, incognito)) return when (r) { - is CR.Invitation -> r.connReqInvitation to r.connection + is CR.Invitation -> (r.connReqInvitation to r.connection) to null else -> { if (!(networkErrorAlert(r))) { - apiErrorAlert("apiAddContact", generalGetString(MR.strings.connection_error), r) + return null to { apiErrorAlert("apiAddContact", generalGetString(MR.strings.connection_error), r) } } - null + null to null } } } @@ -925,10 +931,7 @@ object ChatController { } suspend fun apiConnect(rh: Long?, incognito: Boolean, connReq: String): PendingContactConnection? { - val userId = chatModel.currentUser.value?.userId ?: run { - Log.e(TAG, "apiConnect: no current user") - return null - } + val userId = try { currentUserId("apiConnect") } catch (e: Exception) { return null } val r = sendCmd(rh, CC.APIConnect(userId, incognito, connReq)) when { r is CR.SentConfirmation -> return r.connection @@ -967,10 +970,7 @@ object ChatController { } suspend fun apiConnectContactViaAddress(rh: Long?, incognito: Boolean, contactId: Long): Contact? { - val userId = chatModel.currentUser.value?.userId ?: run { - Log.e(TAG, "apiConnectContactViaAddress: no current user") - return null - } + val userId = try { currentUserId("apiConnectContactViaAddress") } catch (e: Exception) { return null } val r = sendCmd(rh, CC.ApiConnectContactViaAddress(userId, incognito, contactId)) when { r is CR.SentInvitationToContact -> return r.contact @@ -983,23 +983,45 @@ object ChatController { } } + suspend fun deleteChat(chat: Chat, notify: Boolean? = null) { + val cInfo = chat.chatInfo + if (apiDeleteChat(rh = chat.remoteHostId, type = cInfo.chatType, id = cInfo.apiId, notify = notify)) { + chatModel.removeChat(chat.remoteHostId, cInfo.id) + } + } + suspend fun apiDeleteChat(rh: Long?, type: ChatType, id: Long, notify: Boolean? = null): Boolean { + chatModel.deletedChats.value += rh to type.type + id val r = sendCmd(rh, CC.ApiDeleteChat(type, id, notify)) - when { - r is CR.ContactDeleted && type == ChatType.Direct -> return true - r is CR.ContactConnectionDeleted && type == ChatType.ContactConnection -> return true - r is CR.GroupDeletedUser && type == ChatType.Group -> return true + val success = when { + r is CR.ContactDeleted && type == ChatType.Direct -> true + r is CR.ContactConnectionDeleted && type == ChatType.ContactConnection -> true + r is CR.GroupDeletedUser && type == ChatType.Group -> true else -> { val titleId = when (type) { ChatType.Direct -> MR.strings.error_deleting_contact ChatType.Group -> MR.strings.error_deleting_group + ChatType.Local -> MR.strings.error_deleting_note_folder ChatType.ContactRequest -> MR.strings.error_deleting_contact_request ChatType.ContactConnection -> MR.strings.error_deleting_pending_contact_connection } apiErrorAlert("apiDeleteChat", generalGetString(titleId), r) + false + } + } + chatModel.deletedChats.value -= rh to type.type + id + return success + } + + fun clearChat(chat: Chat, close: (() -> Unit)? = null) { + withBGApi { + val updatedChatInfo = apiClearChat(chat.remoteHostId, chat.chatInfo.chatType, chat.chatInfo.apiId) + if (updatedChatInfo != null) { + chatModel.clearChat(chat.remoteHostId, updatedChatInfo) + ntfManager.cancelNotificationsForChat(chat.chatInfo.id) + close?.invoke() } } - return false } suspend fun apiClearChat(rh: Long?, type: ChatType, id: Long): ChatInfo? { @@ -1128,6 +1150,13 @@ object ChatController { return false } + suspend fun apiGetCallInvitations(rh: Long?): List<RcvCallInvitation> { + val r = sendCmd(rh, CC.ApiGetCallInvitations()) + if (r is CR.CallInvitations) return r.callInvitations + Log.e(TAG, "apiGetCallInvitations bad response: ${r.responseType} ${r.details}") + return emptyList() + } + suspend fun apiSendCallInvitation(rh: Long?, contact: Contact, callType: CallType): Boolean { val r = sendCmd(rh, CC.ApiSendCallInvitation(contact, callType)) return r is CR.CmdOk @@ -1303,6 +1332,17 @@ object ChatController { } } + suspend fun apiBlockMemberForAll(rh: Long?, groupId: Long, memberId: Long, blocked: Boolean): GroupMember = + when (val r = sendCmd(rh, CC.ApiBlockMemberForAll(groupId, memberId, blocked))) { + is CR.MemberBlockedForAllUser -> r.member + else -> { + if (!(networkErrorAlert(r))) { + apiErrorAlert("apiBlockMemberForAll", generalGetString(MR.strings.error_blocking_member_for_all), r) + } + throw Exception("failed to block member for all: ${r.responseType} ${r.details}") + } + } + suspend fun apiLeaveGroup(rh: Long?, groupId: Long): GroupInfo? { val r = sendCmd(rh, CC.ApiLeaveGroup(groupId)) if (r is CR.LeftMemberUser) return r.groupInfo @@ -1570,7 +1610,7 @@ object ChatController { chatModel.updateContact(rhId, r.contact) val conn = r.contact.activeConn if (conn != null) { - chatModel.dismissConnReqView(conn.id) + chatModel.replaceConnReqView(conn.id, "@${r.contact.contactId}") chatModel.removeChat(rhId, conn.id) } } @@ -1584,7 +1624,7 @@ object ChatController { chatModel.updateContact(rhId, r.contact) val conn = r.contact.activeConn if (conn != null) { - chatModel.dismissConnReqView(conn.id) + chatModel.replaceConnReqView(conn.id, "@${r.contact.contactId}") chatModel.removeChat(rhId, conn.id) } } @@ -1660,7 +1700,7 @@ object ChatController { ((mc is MsgContent.MCImage && file.fileSize <= MAX_IMAGE_SIZE_AUTO_RCV) || (mc is MsgContent.MCVideo && file.fileSize <= MAX_VIDEO_SIZE_AUTO_RCV) || (mc is MsgContent.MCVoice && file.fileSize <= MAX_VOICE_SIZE_AUTO_RCV && file.fileStatus !is CIFileStatus.RcvAccepted))) { - withApi { receiveFile(rhId, r.user, file.fileId, encrypted = cItem.encryptLocalFile && chatController.appPrefs.privacyEncryptLocalFiles.get(), auto = true) } + withBGApi { receiveFile(rhId, r.user, file.fileId, auto = true) } } if (cItem.showNotification && (allowedToShowNotification() || chatModel.chatId.value != cInfo.id || chatModel.remoteHostId() != rhId)) { ntfManager.notifyMessageReceived(r.user, cInfo, cItem) @@ -1719,7 +1759,7 @@ object ChatController { chatModel.updateGroup(rhId, r.groupInfo) val conn = r.hostContact?.activeConn if (conn != null) { - chatModel.dismissConnReqView(conn.id) + chatModel.replaceConnReqView(conn.id, "#${r.groupInfo.groupId}") chatModel.removeChat(rhId, conn.id) } } @@ -1729,7 +1769,7 @@ object ChatController { chatModel.updateGroup(rhId, r.groupInfo) val hostConn = r.hostMember.activeConn if (hostConn != null) { - chatModel.dismissConnReqView(hostConn.id) + chatModel.replaceConnReqView(hostConn.id, "#${r.groupInfo.groupId}") chatModel.removeChat(rhId, hostConn.id) } } @@ -1757,6 +1797,10 @@ object ChatController { if (active(r.user)) { chatModel.upsertGroupMember(rhId, r.groupInfo, r.member) } + is CR.MemberBlockedForAll -> + if (active(r.user)) { + chatModel.upsertGroupMember(rhId, r.groupInfo, r.member) + } is CR.GroupDeleted -> // TODO update user member if (active(r.user)) { chatModel.updateGroup(rhId, r.groupInfo) @@ -1858,10 +1902,8 @@ object ChatController { } withCall(r, r.contact) { _ -> chatModel.callCommand.add(WCallCommand.End) - withApi { - chatModel.activeCall.value = null - chatModel.showCallView.value = false - } + chatModel.activeCall.value = null + chatModel.showCallView.value = false } } is CR.ContactSwitch -> @@ -1884,9 +1926,34 @@ object ChatController { val disconnectedHost = chatModel.remoteHosts.firstOrNull { it.remoteHostId == r.remoteHostId_ } chatModel.remoteHostPairing.value = null if (disconnectedHost != null) { - showToast( - generalGetString(MR.strings.remote_host_was_disconnected_toast).format(disconnectedHost.hostDeviceName.ifEmpty { disconnectedHost.remoteHostId.toString() }) - ) + val deviceName = disconnectedHost.hostDeviceName.ifEmpty { disconnectedHost.remoteHostId.toString() } + when (r.rhStopReason) { + is RemoteHostStopReason.ConnectionFailed -> { + AlertManager.shared.showAlertMsg( + generalGetString(MR.strings.remote_host_was_disconnected_title), + if (r.rhStopReason.chatError is ChatError.ChatErrorRemoteHost) { + r.rhStopReason.chatError.remoteHostError.localizedString(deviceName) + } else { + generalGetString(MR.strings.remote_host_disconnected_from).format(deviceName, r.rhStopReason.chatError.string) + } + ) + } + is RemoteHostStopReason.Crashed -> { + AlertManager.shared.showAlertMsg( + generalGetString(MR.strings.remote_host_was_disconnected_title), + if (r.rhStopReason.chatError is ChatError.ChatErrorRemoteHost) { + r.rhStopReason.chatError.remoteHostError.localizedString(deviceName) + } else { + generalGetString(MR.strings.remote_host_disconnected_from).format(deviceName, r.rhStopReason.chatError.string) + } + ) + } + is RemoteHostStopReason.Disconnected -> { + if (r.rhsState is RemoteHostSessionState.Connected || r.rhsState is RemoteHostSessionState.Confirmed) { + showToast(generalGetString(MR.strings.remote_host_was_disconnected_toast).format(deviceName)) + } + } + } } if (chatModel.remoteHostId() == r.remoteHostId_) { chatModel.currentRemoteHost.value = null @@ -1917,6 +1984,27 @@ object ChatController { val sess = chatModel.remoteCtrlSession.value if (sess != null) { chatModel.remoteCtrlSession.value = null + fun showAlert(chatError: ChatError) { + AlertManager.shared.showAlertMsg( + generalGetString(MR.strings.remote_ctrl_was_disconnected_title), + if (chatError is ChatError.ChatErrorRemoteCtrl) { + chatError.remoteCtrlError.localizedString + } else { + generalGetString(MR.strings.remote_ctrl_disconnected_with_reason).format(chatError.string) + } + ) + } + when (r.rcStopReason) { + is RemoteCtrlStopReason.DiscoveryFailed -> showAlert(r.rcStopReason.chatError) + is RemoteCtrlStopReason.ConnectionFailed -> showAlert(r.rcStopReason.chatError) + is RemoteCtrlStopReason.SetupFailed -> showAlert(r.rcStopReason.chatError) + is RemoteCtrlStopReason.Disconnected -> { + /*AlertManager.shared.showAlertMsg( + generalGetString(MR.strings.remote_ctrl_was_disconnected_title), + )*/ + } + } + if (sess.sessionState is UIRemoteCtrlSessionState.Connected) { switchToLocalSession() } @@ -1926,7 +2014,7 @@ object ChatController { r.chatError is ChatError.ChatErrorAgent && r.chatError.agentError is AgentErrorType.CRITICAL -> { chatModel.processedCriticalError.newError(r.chatError.agentError, r.chatError.agentError.offerRestart) } - r.chatError is ChatError.ChatErrorAgent && r.chatError.agentError is AgentErrorType.INTERNAL && appPrefs.showInternalErrors.get() -> { + r.chatError is ChatError.ChatErrorAgent && r.chatError.agentError is AgentErrorType.INTERNAL && appPrefs.developerTools.get() && appPrefs.showInternalErrors.get() -> { chatModel.processedInternalError.newError(r.chatError.agentError, false) } } @@ -1953,20 +2041,18 @@ object ChatController { } } - fun switchToLocalSession() { + suspend fun switchToLocalSession() { val m = chatModel m.remoteCtrlSession.value = null - withBGApi { - val users = listUsers(null) - m.users.clear() - m.users.addAll(users) - getUserChatData(null) - val statuses = apiGetNetworkStatuses(null) - if (statuses != null) { - chatModel.networkStatuses.clear() - val ss = statuses.associate { it.agentConnId to it.networkStatus }.toMap() - chatModel.networkStatuses.putAll(ss) - } + val users = listUsers(null) + m.users.clear() + m.users.addAll(users) + getUserChatData(null) + val statuses = apiGetNetworkStatuses(null) + if (statuses != null) { + chatModel.networkStatuses.clear() + val ss = statuses.associate { it.agentConnId to it.networkStatus }.toMap() + chatModel.networkStatuses.putAll(ss) } } @@ -1982,7 +2068,8 @@ object ChatController { } } - suspend fun receiveFile(rhId: Long?, user: UserLike, fileId: Long, encrypted: Boolean, auto: Boolean = false) { + suspend fun receiveFile(rhId: Long?, user: UserLike, fileId: Long, auto: Boolean = false) { + val encrypted = appPrefs.privacyEncryptLocalFiles.get() val chatItem = apiReceiveFile(rhId, fileId, encrypted = encrypted, auto = auto) if (chatItem != null) { chatItemSimpleUpdate(rhId, user, chatItem) @@ -2151,7 +2238,15 @@ class SharedPreference<T>(val get: () -> T, set: (T) -> Unit) { init { this.set = { value -> set(value) - _state.value = value + try { + _state.value = value + } catch (e: IllegalStateException) { + // Can be `Reading a state that was created after the snapshot was taken or in a snapshot that has not yet been applied` + Log.i(TAG, e.stackTraceToString()) + withApi { + _state.value = value + } + } } } } @@ -2186,6 +2281,7 @@ sealed class CC { class ApiGetChat(val type: ChatType, val id: Long, val pagination: ChatPagination, val search: String = ""): CC() class ApiGetChatItemInfo(val type: ChatType, val id: Long, val itemId: Long): CC() class ApiSendMessage(val type: ChatType, val id: Long, val file: CryptoFile?, val quotedItemId: Long?, val mc: MsgContent, val live: Boolean, val ttl: Int?): CC() + class ApiCreateChatItem(val noteFolderId: Long, val file: CryptoFile?, val mc: MsgContent): CC() class ApiUpdateChatItem(val type: ChatType, val id: Long, val itemId: Long, val mc: MsgContent, val live: Boolean): CC() class ApiDeleteChatItem(val type: ChatType, val id: Long, val itemId: Long, val mode: CIDeleteMode): CC() class ApiDeleteMemberChatItem(val groupId: Long, val groupMemberId: Long, val itemId: Long): CC() @@ -2194,6 +2290,7 @@ sealed class CC { class ApiAddMember(val groupId: Long, val contactId: Long, val memberRole: GroupMemberRole): CC() class ApiJoinGroup(val groupId: Long): CC() class ApiMemberRole(val groupId: Long, val memberId: Long, val memberRole: GroupMemberRole): CC() + class ApiBlockMemberForAll(val groupId: Long, val memberId: Long, val blocked: Boolean): CC() class ApiRemoveMember(val groupId: Long, val memberId: Long): CC() class ApiLeaveGroup(val groupId: Long): CC() class ApiListMembers(val groupId: Long): CC() @@ -2242,6 +2339,7 @@ sealed class CC { class ApiShowMyAddress(val userId: Long): CC() class ApiSetProfileAddress(val userId: Long, val on: Boolean): CC() class ApiAddressAutoAccept(val userId: Long, val autoAccept: AutoAccept?): CC() + class ApiGetCallInvitations: CC() class ApiSendCallInvitation(val contact: Contact, val callType: CallType): CC() class ApiRejectCall(val contact: Contact): CC() class ApiSendCallOffer(val contact: Contact, val callOffer: WebRTCCallOffer): CC() @@ -2316,6 +2414,9 @@ sealed class CC { val ttlStr = if (ttl != null) "$ttl" else "default" "/_send ${chatRef(type, id)} live=${onOff(live)} ttl=${ttlStr} json ${json.encodeToString(ComposedMessage(file, quotedItemId, mc))}" } + is ApiCreateChatItem -> { + "/_create *$noteFolderId json ${json.encodeToString(ComposedMessage(file, null, mc))}" + } is ApiUpdateChatItem -> "/_update item ${chatRef(type, id)} $itemId live=${onOff(live)} ${mc.cmdString}" is ApiDeleteChatItem -> "/_delete item ${chatRef(type, id)} $itemId ${mode.deleteMode}" is ApiDeleteMemberChatItem -> "/_delete member item #$groupId $groupMemberId $itemId" @@ -2324,6 +2425,7 @@ sealed class CC { is ApiAddMember -> "/_add #$groupId $contactId ${memberRole.memberRole}" is ApiJoinGroup -> "/_join #$groupId" is ApiMemberRole -> "/_member role #$groupId $memberId ${memberRole.memberRole}" + is ApiBlockMemberForAll -> "/_block #$groupId $memberId blocked=${onOff(blocked)}" is ApiRemoveMember -> "/_remove #$groupId $memberId" is ApiLeaveGroup -> "/_leave #$groupId" is ApiListMembers -> "/_members #$groupId" @@ -2378,6 +2480,7 @@ sealed class CC { is ApiAddressAutoAccept -> "/_auto_accept $userId ${AutoAccept.cmdString(autoAccept)}" is ApiAcceptContact -> "/_accept incognito=${onOff(incognito)} $contactReqId" is ApiRejectContact -> "/_reject $contactReqId" + is ApiGetCallInvitations -> "/_call get" is ApiSendCallInvitation -> "/_call invite @${contact.apiId} ${json.encodeToString(callType)}" is ApiRejectCall -> "/_call reject @${contact.apiId}" is ApiSendCallOffer -> "/_call offer @${contact.apiId} ${json.encodeToString(callOffer)}" @@ -2395,7 +2498,7 @@ sealed class CC { is CancelFile -> "/fcancel $fileId" is SetLocalDeviceName -> "/set device name $displayName" is ListRemoteHosts -> "/list remote hosts" - is StartRemoteHost -> "/start remote host " + (if (remoteHostId == null) "new" else "$remoteHostId multicast=${onOff(multicast)}") + (if (address != null) " addr=${address.address} iface=${address.`interface`}" else "") + (if (port != null) " port=$port" else "") + is StartRemoteHost -> "/start remote host " + (if (remoteHostId == null) "new" else "$remoteHostId multicast=${onOff(multicast)}") + (if (address != null) " addr=${address.address} iface=${json.encodeToString(address.`interface`)}" else "") + (if (port != null) " port=$port" else "") is SwitchRemoteHost -> "/switch remote host " + if (remoteHostId == null) "local" else "$remoteHostId" is StopRemoteHost -> "/stop remote host " + if (remoteHostKey == null) "new" else "$remoteHostKey" is DeleteRemoteHost -> "/delete remote host $remoteHostId" @@ -2443,6 +2546,7 @@ sealed class CC { is ApiGetChat -> "apiGetChat" is ApiGetChatItemInfo -> "apiGetChatItemInfo" is ApiSendMessage -> "apiSendMessage" + is ApiCreateChatItem -> "apiCreateChatItem" is ApiUpdateChatItem -> "apiUpdateChatItem" is ApiDeleteChatItem -> "apiDeleteChatItem" is ApiDeleteMemberChatItem -> "apiDeleteMemberChatItem" @@ -2451,6 +2555,7 @@ sealed class CC { is ApiAddMember -> "apiAddMember" is ApiJoinGroup -> "apiJoinGroup" is ApiMemberRole -> "apiMemberRole" + is ApiBlockMemberForAll -> "apiBlockMemberForAll" is ApiRemoveMember -> "apiRemoveMember" is ApiLeaveGroup -> "apiLeaveGroup" is ApiListMembers -> "apiListMembers" @@ -2501,6 +2606,7 @@ sealed class CC { is ApiAddressAutoAccept -> "apiAddressAutoAccept" is ApiAcceptContact -> "apiAcceptContact" is ApiRejectContact -> "apiRejectContact" + is ApiGetCallInvitations -> "apiGetCallInvitations" is ApiSendCallInvitation -> "apiSendCallInvitation" is ApiRejectCall -> "apiRejectCall" is ApiSendCallOffer -> "apiSendCallOffer" @@ -3314,7 +3420,8 @@ enum class GroupFeature: Feature { @SerialName("fullDelete") FullDelete, @SerialName("reactions") Reactions, @SerialName("voice") Voice, - @SerialName("files") Files; + @SerialName("files") Files, + @SerialName("history") History; override val hasParam: Boolean get() = when(this) { TimedMessages -> true @@ -3329,6 +3436,7 @@ enum class GroupFeature: Feature { Reactions -> generalGetString(MR.strings.message_reactions) Voice -> generalGetString(MR.strings.voice_messages) Files -> generalGetString(MR.strings.files_and_media) + History -> generalGetString(MR.strings.recent_history) } val icon: Painter @@ -3339,6 +3447,7 @@ enum class GroupFeature: Feature { Reactions -> painterResource(MR.images.ic_add_reaction) Voice -> painterResource(MR.images.ic_keyboard_voice) Files -> painterResource(MR.images.ic_draft) + History -> painterResource(MR.images.ic_schedule) } @Composable @@ -3349,6 +3458,7 @@ enum class GroupFeature: Feature { Reactions -> painterResource(MR.images.ic_add_reaction_filled) Voice -> painterResource(MR.images.ic_keyboard_voice_filled) Files -> painterResource(MR.images.ic_draft_filled) + History -> painterResource(MR.images.ic_schedule_filled) } fun enableDescription(enabled: GroupFeatureEnabled, canEdit: Boolean): String = @@ -3378,6 +3488,10 @@ enum class GroupFeature: Feature { GroupFeatureEnabled.ON -> generalGetString(MR.strings.allow_to_send_files) GroupFeatureEnabled.OFF -> generalGetString(MR.strings.prohibit_sending_files) } + History -> when(enabled) { + GroupFeatureEnabled.ON -> generalGetString(MR.strings.enable_sending_recent_history) + GroupFeatureEnabled.OFF -> generalGetString(MR.strings.disable_sending_recent_history) + } } } else { when(this) { @@ -3405,6 +3519,10 @@ enum class GroupFeature: Feature { GroupFeatureEnabled.ON -> generalGetString(MR.strings.group_members_can_send_files) GroupFeatureEnabled.OFF -> generalGetString(MR.strings.files_are_prohibited_in_group) } + History -> when(enabled) { + GroupFeatureEnabled.ON -> generalGetString(MR.strings.recent_history_is_sent_to_new_members) + GroupFeatureEnabled.OFF -> generalGetString(MR.strings.recent_history_is_not_sent_to_new_members) + } } } } @@ -3519,6 +3637,7 @@ data class FullGroupPreferences( val reactions: GroupPreference, val voice: GroupPreference, val files: GroupPreference, + val history: GroupPreference, ) { fun toGroupPreferences(): GroupPreferences = GroupPreferences( @@ -3528,6 +3647,7 @@ data class FullGroupPreferences( reactions = reactions, voice = voice, files = files, + history = history ) companion object { @@ -3538,18 +3658,20 @@ data class FullGroupPreferences( reactions = GroupPreference(GroupFeatureEnabled.ON), voice = GroupPreference(GroupFeatureEnabled.ON), files = GroupPreference(GroupFeatureEnabled.ON), + history = GroupPreference(GroupFeatureEnabled.ON), ) } } @Serializable data class GroupPreferences( - val timedMessages: TimedMessagesGroupPreference?, - val directMessages: GroupPreference?, - val fullDelete: GroupPreference?, - val reactions: GroupPreference?, - val voice: GroupPreference?, - val files: GroupPreference?, + val timedMessages: TimedMessagesGroupPreference? = null, + val directMessages: GroupPreference? = null, + val fullDelete: GroupPreference? = null, + val reactions: GroupPreference? = null, + val voice: GroupPreference? = null, + val files: GroupPreference? = null, + val history: GroupPreference? = null, ) { companion object { val sampleData = GroupPreferences( @@ -3559,6 +3681,7 @@ data class GroupPreferences( reactions = GroupPreference(GroupFeatureEnabled.ON), voice = GroupPreference(GroupFeatureEnabled.ON), files = GroupPreference(GroupFeatureEnabled.ON), + history = GroupPreference(GroupFeatureEnabled.ON), ) } } @@ -3823,6 +3946,8 @@ sealed class CR { @Serializable @SerialName("joinedGroupMemberConnecting") class JoinedGroupMemberConnecting(val user: UserRef, val groupInfo: GroupInfo, val hostMember: GroupMember, val member: GroupMember): CR() @Serializable @SerialName("memberRole") class MemberRole(val user: UserRef, val groupInfo: GroupInfo, val byMember: GroupMember, val member: GroupMember, val fromRole: GroupMemberRole, val toRole: GroupMemberRole): CR() @Serializable @SerialName("memberRoleUser") class MemberRoleUser(val user: UserRef, val groupInfo: GroupInfo, val member: GroupMember, val fromRole: GroupMemberRole, val toRole: GroupMemberRole): CR() + @Serializable @SerialName("memberBlockedForAll") class MemberBlockedForAll(val user: UserRef, val groupInfo: GroupInfo, val byMember: GroupMember, val member: GroupMember, val blocked: Boolean): CR() + @Serializable @SerialName("memberBlockedForAllUser") class MemberBlockedForAllUser(val user: UserRef, val groupInfo: GroupInfo, val member: GroupMember, val blocked: Boolean): CR() @Serializable @SerialName("deletedMemberUser") class DeletedMemberUser(val user: UserRef, val groupInfo: GroupInfo, val member: GroupMember): CR() @Serializable @SerialName("deletedMember") class DeletedMember(val user: UserRef, val groupInfo: GroupInfo, val byMember: GroupMember, val deletedMember: GroupMember): CR() @Serializable @SerialName("leftMember") class LeftMember(val user: UserRef, val groupInfo: GroupInfo, val member: GroupMember): CR() @@ -3859,6 +3984,7 @@ sealed class CR { @Serializable @SerialName("sndFileError") class SndFileError(val user: UserRef, val chatItem: AChatItem): CR() // call events @Serializable @SerialName("callInvitation") class CallInvitation(val callInvitation: RcvCallInvitation): CR() + @Serializable @SerialName("callInvitations") class CallInvitations(val callInvitations: List<RcvCallInvitation>): CR() @Serializable @SerialName("callOffer") class CallOffer(val user: UserRef, val contact: Contact, val callType: CallType, val offer: WebRTCSession, val sharedKey: String? = null, val askConfirmation: Boolean): CR() @Serializable @SerialName("callAnswer") class CallAnswer(val user: UserRef, val contact: Contact, val answer: WebRTCSession): CR() @Serializable @SerialName("callExtraInfo") class CallExtraInfo(val user: UserRef, val contact: Contact, val extraInfo: WebRTCExtraInfo): CR() @@ -3974,6 +4100,8 @@ sealed class CR { is JoinedGroupMemberConnecting -> "joinedGroupMemberConnecting" is MemberRole -> "memberRole" is MemberRoleUser -> "memberRoleUser" + is MemberBlockedForAll -> "memberBlockedForAll" + is MemberBlockedForAllUser -> "memberBlockedForAllUser" is DeletedMemberUser -> "deletedMemberUser" is DeletedMember -> "deletedMember" is LeftMember -> "leftMember" @@ -4006,6 +4134,7 @@ sealed class CR { is SndFileProgressXFTP -> "sndFileProgressXFTP" is SndFileCompleteXFTP -> "sndFileCompleteXFTP" is SndFileError -> "sndFileError" + is CallInvitations -> "callInvitations" is CallInvitation -> "callInvitation" is CallOffer -> "callOffer" is CallAnswer -> "callAnswer" @@ -4120,6 +4249,8 @@ sealed class CR { is JoinedGroupMemberConnecting -> withUser(user, "groupInfo: $groupInfo\nhostMember: $hostMember\nmember: $member") is MemberRole -> withUser(user, "groupInfo: $groupInfo\nbyMember: $byMember\nmember: $member\nfromRole: $fromRole\ntoRole: $toRole") is MemberRoleUser -> withUser(user, "groupInfo: $groupInfo\nmember: $member\nfromRole: $fromRole\ntoRole: $toRole") + is MemberBlockedForAll -> withUser(user, "groupInfo: $groupInfo\nbyMember: $byMember\nmember: $member\nblocked: $blocked") + is MemberBlockedForAllUser -> withUser(user, "groupInfo: $groupInfo\nmember: $member\nblocked: $blocked") is DeletedMemberUser -> withUser(user, "groupInfo: $groupInfo\nmember: $member") is DeletedMember -> withUser(user, "groupInfo: $groupInfo\nbyMember: $byMember\ndeletedMember: $deletedMember") is LeftMember -> withUser(user, "groupInfo: $groupInfo\nmember: $member") @@ -4152,6 +4283,7 @@ sealed class CR { is SndFileProgressXFTP -> withUser(user, "chatItem: ${json.encodeToString(chatItem)}\nsentSize: $sentSize\ntotalSize: $totalSize") is SndFileCompleteXFTP -> withUser(user, json.encodeToString(chatItem)) is SndFileError -> withUser(user, json.encodeToString(chatItem)) + is CallInvitations -> "callInvitations: ${json.encodeToString(callInvitations)}" is CallInvitation -> "contact: ${callInvitation.contact.id}\ncallType: $callInvitation.callType\nsharedKey: ${callInvitation.sharedKey ?: ""}" is CallOffer -> withUser(user, "contact: ${contact.id}\ncallType: $callType\nsharedKey: ${sharedKey ?: ""}\naskConfirmation: $askConfirmation\noffer: ${json.encodeToString(offer)}") is CallAnswer -> withUser(user, "contact: ${contact.id}\nanswer: ${json.encodeToString(answer)}") @@ -4426,6 +4558,7 @@ sealed class ChatErrorType { is EmptyUserPassword -> "emptyUserPassword" is UserAlreadyHidden -> "userAlreadyHidden" is UserNotHidden -> "userNotHidden" + is InvalidDisplayName -> "invalidDisplayName" is ChatNotStarted -> "chatNotStarted" is ChatNotStopped -> "chatNotStopped" is ChatStoreChanged -> "chatStoreChanged" @@ -4503,6 +4636,7 @@ sealed class ChatErrorType { @Serializable @SerialName("emptyUserPassword") class EmptyUserPassword(val userId: Long): ChatErrorType() @Serializable @SerialName("userAlreadyHidden") class UserAlreadyHidden(val userId: Long): ChatErrorType() @Serializable @SerialName("userNotHidden") class UserNotHidden(val userId: Long): ChatErrorType() + @Serializable @SerialName("invalidDisplayName") object InvalidDisplayName: ChatErrorType() @Serializable @SerialName("chatNotStarted") object ChatNotStarted: ChatErrorType() @Serializable @SerialName("chatNotStopped") object ChatNotStopped: ChatErrorType() @Serializable @SerialName("chatStoreChanged") object ChatStoreChanged: ChatErrorType() @@ -4952,6 +5086,15 @@ sealed class RemoteHostError { is BadVersion -> "badVersion" is Disconnected -> "disconnected" } + fun localizedString(name: String): String = when (this) { + is Missing -> generalGetString(MR.strings.remote_host_error_missing) + is Inactive -> generalGetString(MR.strings.remote_host_error_inactive) + is Busy -> generalGetString(MR.strings.remote_host_error_busy) + is Timeout -> generalGetString(MR.strings.remote_host_error_timeout) + is BadState -> generalGetString(MR.strings.remote_host_error_bad_state) + is BadVersion -> generalGetString(MR.strings.remote_host_error_bad_version) + is Disconnected -> generalGetString(MR.strings.remote_host_error_disconnected) + }.format(name) @Serializable @SerialName("missing") object Missing: RemoteHostError() @Serializable @SerialName("inactive") object Inactive: RemoteHostError() @Serializable @SerialName("busy") object Busy: RemoteHostError() @@ -4972,6 +5115,16 @@ sealed class RemoteCtrlError { is BadInvitation -> "badInvitation" is BadVersion -> "badVersion" } + val localizedString: String get() = when (this) { + is Inactive -> generalGetString(MR.strings.remote_ctrl_error_inactive) + is BadState -> generalGetString(MR.strings.remote_ctrl_error_bad_state) + is Busy -> generalGetString(MR.strings.remote_ctrl_error_busy) + is Timeout -> generalGetString(MR.strings.remote_ctrl_error_timeout) + is Disconnected -> generalGetString(MR.strings.remote_ctrl_error_disconnected) + is BadInvitation -> generalGetString(MR.strings.remote_ctrl_error_bad_invitation) + is BadVersion -> generalGetString(MR.strings.remote_ctrl_error_bad_version) + } + @Serializable @SerialName("inactive") object Inactive: RemoteCtrlError() @Serializable @SerialName("badState") object BadState: RemoteCtrlError() @Serializable @SerialName("busy") object Busy: RemoteCtrlError() diff --git a/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/platform/Core.kt b/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/platform/Core.kt index 7d097efb7a..ec81e54418 100644 --- a/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/platform/Core.kt +++ b/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/platform/Core.kt @@ -1,8 +1,13 @@ package chat.simplex.common.platform import chat.simplex.common.model.* +import chat.simplex.common.model.ChatModel.controller +import chat.simplex.common.model.ChatModel.currentUser import chat.simplex.common.views.helpers.* +import chat.simplex.common.views.helpers.DatabaseUtils.ksDatabasePassword import chat.simplex.common.views.onboarding.OnboardingStage +import chat.simplex.res.MR +import kotlinx.coroutines.* import kotlinx.serialization.decodeFromString import java.nio.ByteBuffer @@ -14,6 +19,7 @@ external fun pipeStdOutToSocket(socketName: String) : Int // SimpleX API typealias ChatCtrl = Long external fun chatMigrateInit(dbPath: String, dbKey: String, confirm: String): Array<Any> +external fun chatCloseStore(ctrl: ChatCtrl): String external fun chatSendCmd(ctrl: ChatCtrl, msg: String): String external fun chatSendRemoteCmd(ctrl: ChatCtrl, rhId: Int, msg: String): String external fun chatRecvMsg(ctrl: ChatCtrl): String @@ -35,25 +41,48 @@ val appPreferences: AppPreferences val chatController: ChatController = ChatController -suspend fun initChatController(useKey: String? = null, confirmMigrations: MigrationConfirmation? = null, startChat: Boolean = true) { - val dbKey = useKey ?: DatabaseUtils.useDatabaseKey() - val confirm = confirmMigrations ?: if (appPreferences.confirmDBUpgrades.get()) MigrationConfirmation.Error else MigrationConfirmation.YesUp - val migrated: Array<Any> = chatMigrateInit(dbAbsolutePrefixPath, dbKey, confirm.value) - val res: DBMigrationResult = kotlin.runCatching { - json.decodeFromString<DBMigrationResult>(migrated[0] as String) - }.getOrElse { DBMigrationResult.Unknown(migrated[0] as String) } - val ctrl = if (res is DBMigrationResult.OK) { - migrated[1] as Long - } else null - chatController.ctrl = ctrl - chatModel.chatDbEncrypted.value = dbKey != "" - chatModel.chatDbStatus.value = res - if (res != DBMigrationResult.OK) { - Log.d(TAG, "Unable to migrate successfully: $res") - } else if (startChat) { +fun initChatControllerAndRunMigrations() { + withLongRunningApi(slow = 30_000, deadlock = 60_000) { + if (appPreferences.chatStopped.get() && appPreferences.storeDBPassphrase.get() && ksDatabasePassword.get() != null) { + initChatController(startChat = ::showStartChatAfterRestartAlert) + } else { + initChatController() + } + runMigrations() + } +} + +suspend fun initChatController(useKey: String? = null, confirmMigrations: MigrationConfirmation? = null, startChat: () -> CompletableDeferred<Boolean> = { CompletableDeferred(true) }) { + try { + if (chatModel.ctrlInitInProgress.value) return + chatModel.ctrlInitInProgress.value = true + val dbKey = useKey ?: DatabaseUtils.useDatabaseKey() + val confirm = confirmMigrations ?: if (appPreferences.developerTools.get() && appPreferences.confirmDBUpgrades.get()) MigrationConfirmation.Error else MigrationConfirmation.YesUp + val migrated: Array<Any> = chatMigrateInit(dbAbsolutePrefixPath, dbKey, confirm.value) + val res: DBMigrationResult = kotlin.runCatching { + json.decodeFromString<DBMigrationResult>(migrated[0] as String) + }.getOrElse { DBMigrationResult.Unknown(migrated[0] as String) } + val ctrl = if (res is DBMigrationResult.OK) { + migrated[1] as Long + } else null + chatController.ctrl = ctrl + chatModel.chatDbEncrypted.value = dbKey != "" + chatModel.chatDbStatus.value = res + if (res != DBMigrationResult.OK) { + Log.d(TAG, "Unable to migrate successfully: $res") + return + } + controller.apiSetTempFolder(coreTmpDir.absolutePath) + controller.apiSetFilesFolder(appFilesDir.absolutePath) + if (appPlatform.isDesktop) { + controller.apiSetRemoteHostsFolder(remoteHostsDir.absolutePath) + } + controller.apiSetXFTPConfig(controller.getXFTPCfg()) + controller.apiSetEncryptLocalFiles(controller.appPrefs.privacyEncryptLocalFiles.get()) // If we migrated successfully means previous re-encryption process on database level finished successfully too if (appPreferences.encryptionStartedAt.get() != null) appPreferences.encryptionStartedAt.set(null) val user = chatController.apiGetActiveUser(null) + chatModel.currentUser.value = user if (user == null) { chatModel.controller.appPrefs.privacyDeliveryReceiptsSet.set(true) chatModel.currentUser.value = null @@ -71,18 +100,36 @@ suspend fun initChatController(useKey: String? = null, confirmMigrations: Migrat } else { chatController.appPrefs.onboardingStage.set(OnboardingStage.Step1_SimpleXInfo) } - } else { + } else if (startChat().await()) { val savedOnboardingStage = appPreferences.onboardingStage.get() - appPreferences.onboardingStage.set(if (listOf(OnboardingStage.Step1_SimpleXInfo, OnboardingStage.Step2_CreateProfile).contains(savedOnboardingStage) && chatModel.users.size == 1) { + val newStage = if (listOf(OnboardingStage.Step1_SimpleXInfo, OnboardingStage.Step2_CreateProfile).contains(savedOnboardingStage) && chatModel.users.size == 1) { OnboardingStage.Step3_CreateSimpleXAddress } else { savedOnboardingStage - }) - if (appPreferences.onboardingStage.get() == OnboardingStage.OnboardingComplete && !chatModel.controller.appPrefs.privacyDeliveryReceiptsSet.get()) { - chatModel.setDeliveryReceipts.value = true + } + if (appPreferences.onboardingStage.get() != newStage) { + appPreferences.onboardingStage.set(newStage) } chatController.startChat(user) platform.androidChatInitializedAndStarted() + } else { + chatController.getUserChatData(null) + chatModel.localUserCreated.value = currentUser.value != null + chatModel.chatRunning.value = false } + } finally { + chatModel.ctrlInitInProgress.value = false } } + +fun showStartChatAfterRestartAlert(): CompletableDeferred<Boolean> { + val deferred = CompletableDeferred<Boolean>() + AlertManager.shared.showAlertDialog( + title = generalGetString(MR.strings.start_chat_question), + text = generalGetString(MR.strings.chat_is_stopped_you_should_transfer_database), + onConfirm = { deferred.complete(true) }, + onDismiss = { deferred.complete(false) }, + onDismissRequest = { deferred.complete(false) } + ) + return deferred +} diff --git a/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/platform/Modifier.kt b/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/platform/Modifier.kt index 1141ab21ab..4a10027746 100644 --- a/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/platform/Modifier.kt +++ b/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/platform/Modifier.kt @@ -23,3 +23,5 @@ expect fun Modifier.desktopOnExternalDrag( ): Modifier expect fun Modifier.onRightClick(action: () -> Unit): Modifier + +expect fun Modifier.desktopPointerHoverIconHand(): Modifier diff --git a/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/platform/NtfManager.kt b/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/platform/NtfManager.kt index c9ede4848e..a75ee75903 100644 --- a/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/platform/NtfManager.kt +++ b/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/platform/NtfManager.kt @@ -55,7 +55,7 @@ abstract class NtfManager { } fun openChatAction(userId: Long?, chatId: ChatId) { - withBGApi { + withLongRunningApi(slow = 30_000, deadlock = 60_000) { awaitChatStartedIfNeeded(chatModel) if (userId != null && userId != chatModel.currentUser.value?.userId && chatModel.currentUser.value != null) { // TODO include remote host ID in desktop notifications? @@ -70,7 +70,7 @@ abstract class NtfManager { } fun showChatsAction(userId: Long?) { - withBGApi { + withLongRunningApi(slow = 30_000, deadlock = 60_000) { awaitChatStartedIfNeeded(chatModel) if (userId != null && userId != chatModel.currentUser.value?.userId && chatModel.currentUser.value != null) { // TODO include remote host ID in desktop notifications? diff --git a/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/ui/theme/Color.kt b/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/ui/theme/Color.kt index a01fc9de51..5eeedbb2a0 100644 --- a/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/ui/theme/Color.kt +++ b/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/ui/theme/Color.kt @@ -1,6 +1,12 @@ package chat.simplex.common.ui.theme -import androidx.compose.ui.graphics.Color +import androidx.compose.material.LocalContentColor +import androidx.compose.material.MaterialTheme +import androidx.compose.runtime.Composable +import androidx.compose.runtime.collectAsState +import androidx.compose.ui.graphics.* +import chat.simplex.common.views.helpers.mixWith +import kotlin.math.min val Purple200 = Color(0xFFBB86FC) val Purple500 = Color(0xFF6200EE) @@ -25,4 +31,17 @@ val WarningOrange = Color(255, 127, 0, 255) val WarningYellow = Color(255, 192, 0, 255) val FileLight = Color(183, 190, 199, 255) val FileDark = Color(101, 101, 106, 255) -val MenuTextColorDark = Color.White.copy(alpha = 0.8f) +val SentMessageColor = Color(0x1E45B8FF) + +val MenuTextColor: Color @Composable get () = if (isInDarkTheme()) LocalContentColor.current.copy(alpha = 0.8f) else Color.Black +val NoteFolderIconColor: Color @Composable get() = with(CurrentColors.collectAsState().value.appColors.sentMessage) { + // Default color looks too light and better to have it here a little bit brighter + if (alpha == SentMessageColor.alpha) { + copy(min(SentMessageColor.alpha + 0.1f, 1f)) + } else { + // Color is non-standard and theme maker can choose color without alpha at all since the theme bound to dark/light variant, + // and it shouldn't be universal + this + } +} + diff --git a/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/ui/theme/Theme.kt b/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/ui/theme/Theme.kt index 6af3156ca2..5cf05f64c5 100644 --- a/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/ui/theme/Theme.kt +++ b/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/ui/theme/Theme.kt @@ -6,6 +6,7 @@ import androidx.compose.runtime.* import androidx.compose.ui.Modifier import androidx.compose.ui.geometry.Offset import androidx.compose.ui.graphics.* +import androidx.compose.ui.text.TextStyle import androidx.compose.ui.unit.dp import chat.simplex.common.model.ChatController import chat.simplex.common.platform.isInNightMode @@ -211,7 +212,7 @@ val DarkColorPalette = darkColors( ) val DarkColorPaletteApp = AppColors( title = SimplexBlue, - sentMessage = Color(0x1E45B8FF), + sentMessage = SentMessageColor, receivedMessage = Color(0x20B1B0B5) ) @@ -230,7 +231,7 @@ val LightColorPalette = lightColors( ) val LightColorPaletteApp = AppColors( title = SimplexBlue, - sentMessage = Color(0x1E45B8FF), + sentMessage = SentMessageColor, receivedMessage = Color(0x20B1B0B5) ) @@ -250,7 +251,7 @@ val SimplexColorPalette = darkColors( ) val SimplexColorPaletteApp = AppColors( title = Color(0xFF267BE5), - sentMessage = Color(0x1E45B8FF), + sentMessage = SentMessageColor, receivedMessage = Color(0x20B1B0B5) ) @@ -284,6 +285,8 @@ fun SimpleXTheme(darkTheme: Boolean? = null, content: @Composable () -> Unit) { colors = theme.colors, typography = Typography, shapes = Shapes, - content = content + content = { + CompositionLocalProvider(LocalContentColor provides MaterialTheme.colors.onBackground, content = content) + } ) } diff --git a/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/views/SplashView.kt b/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/views/SplashView.kt index cf9a8dfb62..5265f3187b 100644 --- a/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/views/SplashView.kt +++ b/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/views/SplashView.kt @@ -1,8 +1,7 @@ package chat.simplex.common.views import androidx.compose.foundation.layout.fillMaxSize -import androidx.compose.material.MaterialTheme -import androidx.compose.material.Surface +import androidx.compose.material.* import androidx.compose.runtime.Composable import androidx.compose.ui.Modifier @@ -11,7 +10,8 @@ fun SplashView() { Surface( Modifier .fillMaxSize(), - color = MaterialTheme.colors.background + color = MaterialTheme.colors.background, + contentColor = LocalContentColor.current ) { // Image( // painter = painterResource(MR.images.logo), diff --git a/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/views/TerminalView.kt b/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/views/TerminalView.kt index 4f01d4a39f..bcdf2e8380 100644 --- a/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/views/TerminalView.kt +++ b/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/views/TerminalView.kt @@ -50,7 +50,7 @@ private fun sendCommand(chatModel: ChatModel, composeState: MutableState<Compose chatModel.addTerminalItem(TerminalItem.resp(null, resp)) composeState.value = ComposeState(useLinkPreviews = false) } else { - withApi { + withBGApi { // show "in progress" // TODO show active remote host in chat console? chatModel.controller.sendCmd(chatModel.remoteHostId(), CC.Console(s)) @@ -101,13 +101,16 @@ fun TerminalLayout( ) } }, + contentColor = LocalContentColor.current, + drawerContentColor = LocalContentColor.current, modifier = Modifier.navigationBarsWithImePadding() ) { contentPadding -> Surface( modifier = Modifier .padding(contentPadding) .fillMaxWidth(), - color = MaterialTheme.colors.background + color = MaterialTheme.colors.background, + contentColor = LocalContentColor.current ) { TerminalLog() } diff --git a/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/views/WelcomeView.kt b/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/views/WelcomeView.kt index 29d7033290..c4cbe06831 100644 --- a/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/views/WelcomeView.kt +++ b/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/views/WelcomeView.kt @@ -175,10 +175,12 @@ fun CreateFirstProfile(chatModel: ChatModel, close: () -> Unit) { } fun createProfileInNoProfileSetup(displayName: String, close: () -> Unit) { - withApi { - val user = controller.apiCreateActiveUser(null, Profile(displayName.trim(), "", null)) ?: return@withApi + withBGApi { + val user = controller.apiCreateActiveUser(null, Profile(displayName.trim(), "", null)) ?: return@withBGApi + if (!chatModel.connectedToRemote()) { + chatModel.localUserCreated.value = true + } controller.appPrefs.onboardingStage.set(OnboardingStage.Step3_CreateSimpleXAddress) - chatModel.chatRunning.value = false controller.startChat(user) controller.switchUIRemoteHost(null) close() @@ -186,11 +188,11 @@ fun createProfileInNoProfileSetup(displayName: String, close: () -> Unit) { } fun createProfileInProfiles(chatModel: ChatModel, displayName: String, close: () -> Unit) { - withApi { + withBGApi { val rhId = chatModel.remoteHostId() val user = chatModel.controller.apiCreateActiveUser( rhId, Profile(displayName.trim(), "", null) - ) ?: return@withApi + ) ?: return@withBGApi chatModel.currentUser.value = user if (chatModel.users.isEmpty()) { chatModel.controller.startChat(user) @@ -206,10 +208,11 @@ fun createProfileInProfiles(chatModel: ChatModel, displayName: String, close: () } fun createProfileOnboarding(chatModel: ChatModel, displayName: String, close: () -> Unit) { - withApi { + withBGApi { chatModel.currentUser.value = chatModel.controller.apiCreateActiveUser( null, Profile(displayName.trim(), "", null) - ) ?: return@withApi + ) ?: return@withBGApi + chatModel.localUserCreated.value = true val onboardingStage = chatModel.controller.appPrefs.onboardingStage if (chatModel.users.isEmpty()) { onboardingStage.set(if (appPlatform.isDesktop && chatModel.controller.appPrefs.initialRandomDBPassphrase.get() && !chatModel.desktopOnboardingRandomPassword.value) { @@ -239,7 +242,7 @@ fun OnboardingButtons(displayName: MutableState<String>, close: () -> Unit) { val enabled = canCreateProfile(displayName.value) val createModifier: Modifier = Modifier.clickable(enabled) { createProfileOnboarding(chatModel, displayName.value, close) }.padding(8.dp) val createColor: Color = if (enabled) MaterialTheme.colors.primary else MaterialTheme.colors.secondary - Surface(shape = RoundedCornerShape(20.dp), color = Color.Transparent) { + Surface(shape = RoundedCornerShape(20.dp), color = Color.Transparent, contentColor = LocalContentColor.current) { Row(verticalAlignment = Alignment.CenterVertically, modifier = createModifier) { Text(stringResource(MR.strings.create_profile_button), style = MaterialTheme.typography.caption, color = createColor, fontWeight = FontWeight.Medium) Icon(painterResource(MR.images.ic_arrow_forward_ios), stringResource(MR.strings.create_profile_button), tint = createColor) diff --git a/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/views/call/CallManager.kt b/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/views/call/CallManager.kt index 139c749e59..b215badf2d 100644 --- a/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/views/call/CallManager.kt +++ b/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/views/call/CallManager.kt @@ -2,7 +2,7 @@ package chat.simplex.common.views.call import chat.simplex.common.model.ChatModel import chat.simplex.common.platform.* -import chat.simplex.common.views.helpers.withApi +import chat.simplex.common.views.helpers.withBGApi import kotlinx.datetime.Clock import kotlin.time.Duration.Companion.minutes @@ -28,13 +28,13 @@ class CallManager(val chatModel: ChatModel) { if (call == null) { justAcceptIncomingCall(invitation = invitation) } else { - withApi { + withBGApi { chatModel.switchingCall.value = true try { endCall(call = call) justAcceptIncomingCall(invitation = invitation) } finally { - withApi { chatModel.switchingCall.value = false } + chatModel.switchingCall.value = false } } } @@ -90,7 +90,7 @@ class CallManager(val chatModel: ChatModel) { activeCallInvitation.value = null ntfManager.cancelCallNotification() } - withApi { + withBGApi { if (!controller.apiRejectCall(invitation.remoteHostId, invitation.contact)) { Log.e(TAG, "apiRejectCall error") } diff --git a/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/views/call/IncomingCallAlertView.kt b/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/views/call/IncomingCallAlertView.kt index 85d65ae1ee..829a849ddc 100644 --- a/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/views/call/IncomingCallAlertView.kt +++ b/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/views/call/IncomingCallAlertView.kt @@ -88,7 +88,8 @@ fun IncomingCallInfo(invitation: RcvCallInvitation, chatModel: ChatModel) { private fun CallButton(text: String, icon: Painter, color: Color, action: () -> Unit) { Surface( shape = RoundedCornerShape(10.dp), - color = Color.Transparent + color = Color.Transparent, + contentColor = LocalContentColor.current ) { Column( Modifier diff --git a/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/views/chat/ChatInfoView.kt b/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/views/chat/ChatInfoView.kt index 694ec2ba18..f195c723f6 100644 --- a/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/views/chat/ChatInfoView.kt +++ b/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/views/chat/ChatInfoView.kt @@ -29,6 +29,7 @@ import androidx.compose.ui.text.style.TextOverflow import androidx.compose.ui.unit.dp import androidx.compose.ui.unit.sp import chat.simplex.common.model.* +import chat.simplex.common.model.ChatModel.controller import chat.simplex.common.ui.theme.* import chat.simplex.common.views.helpers.* import chat.simplex.common.views.usersettings.* @@ -69,11 +70,9 @@ fun ChatInfoView( currentUser, sendReceipts = sendReceipts, setSendReceipts = { sendRcpts -> - withApi { - val chatSettings = (chat.chatInfo.chatSettings ?: ChatSettings.defaults).copy(sendRcpts = sendRcpts.bool) - updateChatSettings(chat, chatSettings, chatModel) - sendReceipts.value = sendRcpts - } + val chatSettings = (chat.chatInfo.chatSettings ?: ChatSettings.defaults).copy(sendRcpts = sendRcpts.bool) + updateChatSettings(chat, chatSettings, chatModel) + sendReceipts.value = sendRcpts }, connStats = connStats, contactNetworkStatus.value, @@ -93,10 +92,10 @@ fun ChatInfoView( } }, deleteContact = { deleteContactDialog(chat, chatModel, close) }, - clearChat = { clearChatDialog(chat, chatModel, close) }, + clearChat = { clearChatDialog(chat, close) }, switchContactAddress = { showSwitchAddressAlert(switchAddress = { - withApi { + withBGApi { val cStats = chatModel.controller.apiSwitchContact(chatRh, contact.contactId) connStats.value = cStats if (cStats != null) { @@ -108,7 +107,7 @@ fun ChatInfoView( }, abortSwitchContactAddress = { showAbortSwitchAddressAlert(abortSwitchAddress = { - withApi { + withBGApi { val cStats = chatModel.controller.apiAbortSwitchContact(chatRh, contact.contactId) connStats.value = cStats if (cStats != null) { @@ -118,7 +117,7 @@ fun ChatInfoView( }) }, syncContactConnection = { - withApi { + withBGApi { val cStats = chatModel.controller.apiSyncContactRatchet(chatRh, contact.contactId, force = false) connStats.value = cStats if (cStats != null) { @@ -129,7 +128,7 @@ fun ChatInfoView( }, syncContactConnectionForce = { showSyncConnectionForceAlert(syncConnectionForce = { - withApi { + withBGApi { val cStats = chatModel.controller.apiSyncContactRatchet(chatRh, contact.contactId, force = true) connStats.value = cStats if (cStats != null) { @@ -208,18 +207,14 @@ fun deleteContactDialog(chat: Chat, chatModel: ChatModel, close: (() -> Unit)? = // Delete and notify contact SectionItemView({ AlertManager.shared.hideAlert() - withApi { - deleteContact(chat, chatModel, close, notify = true) - } + deleteContact(chat, chatModel, close, notify = true) }) { Text(generalGetString(MR.strings.delete_and_notify_contact), Modifier.fillMaxWidth(), textAlign = TextAlign.Center, color = MaterialTheme.colors.error) } // Delete SectionItemView({ AlertManager.shared.hideAlert() - withApi { - deleteContact(chat, chatModel, close, notify = false) - } + deleteContact(chat, chatModel, close, notify = false) }) { Text(generalGetString(MR.strings.delete_verb), Modifier.fillMaxWidth(), textAlign = TextAlign.Center, color = MaterialTheme.colors.error) } @@ -227,9 +222,7 @@ fun deleteContactDialog(chat: Chat, chatModel: ChatModel, close: (() -> Unit)? = // Delete SectionItemView({ AlertManager.shared.hideAlert() - withApi { - deleteContact(chat, chatModel, close) - } + deleteContact(chat, chatModel, close) }) { Text(generalGetString(MR.strings.delete_verb), Modifier.fillMaxWidth(), textAlign = TextAlign.Center, color = MaterialTheme.colors.error) } @@ -247,7 +240,7 @@ fun deleteContactDialog(chat: Chat, chatModel: ChatModel, close: (() -> Unit)? = fun deleteContact(chat: Chat, chatModel: ChatModel, close: (() -> Unit)?, notify: Boolean? = null) { val chatInfo = chat.chatInfo - withApi { + withBGApi { val chatRh = chat.remoteHostId val r = chatModel.controller.apiDeleteChat(chatRh, chatInfo.chatType, chatInfo.apiId, notify) if (r) { @@ -262,23 +255,22 @@ fun deleteContact(chat: Chat, chatModel: ChatModel, close: (() -> Unit)?, notify } } -fun clearChatDialog(chat: Chat, chatModel: ChatModel, close: (() -> Unit)? = null) { - val chatInfo = chat.chatInfo +fun clearChatDialog(chat: Chat, close: (() -> Unit)? = null) { AlertManager.shared.showAlertDialog( title = generalGetString(MR.strings.clear_chat_question), text = generalGetString(MR.strings.clear_chat_warning), confirmText = generalGetString(MR.strings.clear_verb), - onConfirm = { - withApi { - val chatRh = chat.remoteHostId - val updatedChatInfo = chatModel.controller.apiClearChat(chatRh, chatInfo.chatType, chatInfo.apiId) - if (updatedChatInfo != null) { - chatModel.clearChat(chatRh, updatedChatInfo) - ntfManager.cancelNotificationsForChat(chatInfo.id) - close?.invoke() - } - } - }, + onConfirm = { controller.clearChat(chat, close) }, + destructive = true, + ) +} + +fun clearNoteFolderDialog(chat: Chat, close: (() -> Unit)? = null) { + AlertManager.shared.showAlertDialog( + title = generalGetString(MR.strings.clear_note_folder_question), + text = generalGetString(MR.strings.clear_note_folder_warning), + confirmText = generalGetString(MR.strings.clear_verb), + onConfirm = { controller.clearChat(chat, close) }, destructive = true, ) } @@ -355,7 +347,7 @@ fun ChatInfoLayout( if (contact.contactLink != null) { SectionView(stringResource(MR.strings.address_section_title).uppercase()) { - SimpleXLinkQRCode(contact.contactLink, Modifier.padding(horizontal = DEFAULT_PADDING, vertical = DEFAULT_PADDING_HALF).aspectRatio(1f)) + SimpleXLinkQRCode(contact.contactLink) val clipboard = LocalClipboardManager.current ShareAddressButton { clipboard.shareText(simplexChatLink(contact.contactLink)) } SectionTextFooter(stringResource(MR.strings.you_can_share_this_address_with_your_contacts).format(contact.displayName)) @@ -676,7 +668,7 @@ fun ShareAddressButton(onClick: () -> Unit) { ) } -private fun setContactAlias(chat: Chat, localAlias: String, chatModel: ChatModel) = withApi { +private fun setContactAlias(chat: Chat, localAlias: String, chatModel: ChatModel) = withBGApi { val chatRh = chat.remoteHostId chatModel.controller.apiSetContactAlias(chatRh, chat.chatInfo.apiId, localAlias)?.let { chatModel.updateContact(chatRh, it) diff --git a/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/views/chat/ChatItemInfoView.kt b/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/views/chat/ChatItemInfoView.kt index 63cd25092e..a468214528 100644 --- a/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/views/chat/ChatItemInfoView.kt +++ b/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/views/chat/ChatItemInfoView.kt @@ -53,6 +53,7 @@ fun ChatItemInfoView(chatModel: ChatModel, ci: ChatItem, ciInfo: ChatItemInfo, d text, if (text.isEmpty()) emptyList() else formattedText, sender = sender, senderBold = true, + toggleSecrets = true, linkMode = SimplexLinkMode.DESCRIPTION, uriHandler = uriHandler, onLinkLongClick = { showMenu.value = true } ) @@ -153,9 +154,9 @@ fun ChatItemInfoView(chatModel: ChatModel, ci: ChatItem, ciInfo: ChatItemInfo, d @Composable fun Details() { - AppBarTitle(stringResource(if (sent) MR.strings.sent_message else MR.strings.received_message)) + AppBarTitle(stringResource(if (ci.localNote) MR.strings.saved_message_title else if (sent) MR.strings.sent_message else MR.strings.received_message)) SectionView { - InfoRow(stringResource(MR.strings.info_row_sent_at), localTimestamp(ci.meta.itemTs)) + InfoRow(stringResource(if (!ci.localNote) MR.strings.info_row_sent_at else MR.strings.info_row_created_at), localTimestamp(ci.meta.itemTs)) if (!sent) { InfoRow(stringResource(MR.strings.info_row_received_at), localTimestamp(ci.meta.createdAt)) } @@ -392,9 +393,9 @@ private fun membersStatuses(chatModel: ChatModel, memberDeliveryStatuses: List<M fun itemInfoShareText(chatModel: ChatModel, ci: ChatItem, chatItemInfo: ChatItemInfo, devTools: Boolean): String { val meta = ci.meta val sent = ci.chatDir.sent - val shareText = mutableListOf<String>("# " + generalGetString(if (sent) MR.strings.sent_message else MR.strings.received_message), "") + val shareText = mutableListOf<String>("# " + generalGetString(if (ci.localNote) MR.strings.saved_message_title else if (sent) MR.strings.sent_message else MR.strings.received_message), "") - shareText.add(String.format(generalGetString(MR.strings.share_text_sent_at), localTimestamp(meta.itemTs))) + shareText.add(String.format(generalGetString(if (ci.localNote) MR.strings.share_text_created_at else MR.strings.share_text_sent_at), localTimestamp(meta.itemTs))) if (!ci.chatDir.sent) { shareText.add(String.format(generalGetString(MR.strings.share_text_received_at), localTimestamp(meta.createdAt))) } diff --git a/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/views/chat/ChatView.kt b/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/views/chat/ChatView.kt index 0e2a7c1680..2e99d791b5 100644 --- a/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/views/chat/ChatView.kt +++ b/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/views/chat/ChatView.kt @@ -24,6 +24,7 @@ import androidx.compose.ui.graphics.ImageBitmap import androidx.compose.ui.text.* import androidx.compose.ui.unit.* import chat.simplex.common.model.* +import chat.simplex.common.model.ChatModel.controller import chat.simplex.common.ui.theme.* import chat.simplex.common.views.call.* import chat.simplex.common.views.chat.group.* @@ -33,6 +34,7 @@ import chat.simplex.common.views.helpers.* import chat.simplex.common.model.GroupInfo import chat.simplex.common.platform.* import chat.simplex.common.platform.AudioPlayer +import chat.simplex.common.views.newchat.ContactConnectionInfoView import chat.simplex.res.MR import kotlinx.coroutines.* import kotlinx.coroutines.flow.* @@ -114,343 +116,374 @@ fun ChatView(chatId: String, chatModel: ChatModel, onComposed: suspend (chatId: } } val clipboard = LocalClipboardManager.current - - ChatLayout( - chat, - unreadCount, - composeState, - composeView = { - Column( - Modifier.fillMaxWidth(), - horizontalAlignment = Alignment.CenterHorizontally - ) { - if ( - chat.chatInfo is ChatInfo.Direct - && !chat.chatInfo.contact.ready - && chat.chatInfo.contact.active - && !chat.chatInfo.contact.nextSendGrpInv - ) { - Text( - generalGetString(MR.strings.contact_connection_pending), - Modifier.padding(top = 4.dp), - fontSize = 14.sp, - color = MaterialTheme.colors.secondary - ) - } - ComposeView( - chatModel, chat, composeState, attachmentOption, - showChooseAttachment = { scope.launch { attachmentBottomSheetState.show() } } - ) - } - }, - attachmentOption, - attachmentBottomSheetState, - chatModel.chatItems, - searchText, - useLinkPreviews = useLinkPreviews, - linkMode = chatModel.simplexLinkMode.value, - back = { - hideKeyboard(view) - AudioPlayer.stop() - chatModel.chatId.value = null - chatModel.groupMembers.clear() - }, - info = { - if (ModalManager.end.hasModalsOpen()) { - ModalManager.end.closeModals() - return@ChatLayout - } - hideKeyboard(view) - withApi { - // The idea is to preload information before showing a modal because large groups can take time to load all members - var preloadedContactInfo: Pair<ConnectionStats?, Profile?>? = null - var preloadedCode: String? = null - var preloadedLink: Pair<String, GroupMemberRole>? = null - if (chat.chatInfo is ChatInfo.Direct) { - preloadedContactInfo = chatModel.controller.apiContactInfo(chatRh, chat.chatInfo.apiId) - preloadedCode = chatModel.controller.apiGetContactCode(chatRh, chat.chatInfo.apiId)?.second - } else if (chat.chatInfo is ChatInfo.Group) { - setGroupMembers(chatRh, chat.chatInfo.groupInfo, chatModel) - preloadedLink = chatModel.controller.apiGetGroupLink(chatRh, chat.chatInfo.groupInfo.groupId) - } - ModalManager.end.showModalCloseable(true) { close -> - val chat = remember { activeChat }.value - if (chat?.chatInfo is ChatInfo.Direct) { - var contactInfo: Pair<ConnectionStats?, Profile?>? by remember { mutableStateOf(preloadedContactInfo) } - var code: String? by remember { mutableStateOf(preloadedCode) } - KeyChangeEffect(chat.id, ChatModel.networkStatuses.toMap()) { - contactInfo = chatModel.controller.apiContactInfo(chatRh, chat.chatInfo.apiId) - preloadedContactInfo = contactInfo - code = chatModel.controller.apiGetContactCode(chatRh, chat.chatInfo.apiId)?.second - preloadedCode = code + when (chat.chatInfo) { + is ChatInfo.Direct, is ChatInfo.Group, is ChatInfo.Local -> { + ChatLayout( + chat, + unreadCount, + composeState, + composeView = { + Column( + Modifier.fillMaxWidth(), + horizontalAlignment = Alignment.CenterHorizontally + ) { + if ( + chat.chatInfo is ChatInfo.Direct + && !chat.chatInfo.contact.ready + && chat.chatInfo.contact.active + && !chat.chatInfo.contact.nextSendGrpInv + ) { + Text( + generalGetString(MR.strings.contact_connection_pending), + Modifier.padding(top = 4.dp), + fontSize = 14.sp, + color = MaterialTheme.colors.secondary + ) } - ChatInfoView(chatModel, (chat.chatInfo as ChatInfo.Direct).contact, contactInfo?.first, contactInfo?.second, chat.chatInfo.localAlias, code, close) - } else if (chat?.chatInfo is ChatInfo.Group) { - var link: Pair<String, GroupMemberRole>? by remember(chat.id) { mutableStateOf(preloadedLink) } - KeyChangeEffect(chat.id) { - setGroupMembers(chatRh, (chat.chatInfo as ChatInfo.Group).groupInfo, chatModel) - link = chatModel.controller.apiGetGroupLink(chatRh, chat.chatInfo.groupInfo.groupId) - preloadedLink = link + ComposeView( + chatModel, chat, composeState, attachmentOption, + showChooseAttachment = { scope.launch { attachmentBottomSheetState.show() } } + ) + } + }, + attachmentOption, + attachmentBottomSheetState, + chatModel.chatItems, + searchText, + useLinkPreviews = useLinkPreviews, + linkMode = chatModel.simplexLinkMode.value, + back = { + hideKeyboard(view) + AudioPlayer.stop() + chatModel.chatId.value = null + chatModel.groupMembers.clear() + }, + info = { + if (ModalManager.end.hasModalsOpen()) { + ModalManager.end.closeModals() + return@ChatLayout + } + hideKeyboard(view) + withBGApi { + // The idea is to preload information before showing a modal because large groups can take time to load all members + var preloadedContactInfo: Pair<ConnectionStats?, Profile?>? = null + var preloadedCode: String? = null + var preloadedLink: Pair<String, GroupMemberRole>? = null + if (chat.chatInfo is ChatInfo.Direct) { + preloadedContactInfo = chatModel.controller.apiContactInfo(chatRh, chat.chatInfo.apiId) + preloadedCode = chatModel.controller.apiGetContactCode(chatRh, chat.chatInfo.apiId)?.second + } else if (chat.chatInfo is ChatInfo.Group) { + setGroupMembers(chatRh, chat.chatInfo.groupInfo, chatModel) + preloadedLink = chatModel.controller.apiGetGroupLink(chatRh, chat.chatInfo.groupInfo.groupId) } - GroupChatInfoView(chatModel, chatRh, chat.id, link?.first, link?.second, { - link = it - preloadedLink = it - }, close) - } - } - } - }, - showMemberInfo = { groupInfo: GroupInfo, member: GroupMember -> - hideKeyboard(view) - withApi { - val r = chatModel.controller.apiGroupMemberInfo(chatRh, groupInfo.groupId, member.groupMemberId) - val stats = r?.second - val (_, code) = if (member.memberActive) { - val memCode = chatModel.controller.apiGetGroupMemberCode(chatRh, groupInfo.apiId, member.groupMemberId) - member to memCode?.second - } else { - member to null - } - setGroupMembers(chatRh, groupInfo, chatModel) - ModalManager.end.closeModals() - ModalManager.end.showModalCloseable(true) { close -> - remember { derivedStateOf { chatModel.getGroupMember(member.groupMemberId) } }.value?.let { mem -> - GroupMemberInfoView(chatRh, groupInfo, mem, stats, code, chatModel, close, close) - } - } - } - }, - loadPrevMessages = { - if (chatModel.chatId.value != activeChat.value?.id) return@ChatLayout - val c = chatModel.getChat(chatModel.chatId.value ?: return@ChatLayout) - val firstId = chatModel.chatItems.firstOrNull()?.id - if (c != null && firstId != null) { - withApi { - Log.d(TAG, "TODOCHAT: loadPrevMessages: loading for ${c.id}, current chatId ${ChatModel.chatId.value}, size was ${ChatModel.chatItems.size}") - apiLoadPrevMessages(c, chatModel, firstId, searchText.value) - Log.d(TAG, "TODOCHAT: loadPrevMessages: loaded for ${c.id}, current chatId ${ChatModel.chatId.value}, size now ${ChatModel.chatItems.size}") - } - } - }, - deleteMessage = { itemId, mode -> - withApi { - val cInfo = chat.chatInfo - val toDeleteItem = chatModel.chatItems.firstOrNull { it.id == itemId } - val toModerate = toDeleteItem?.memberToModerate(chat.chatInfo) - val groupInfo = toModerate?.first - val groupMember = toModerate?.second - val deletedChatItem: ChatItem? - val toChatItem: ChatItem? - if (mode == CIDeleteMode.cidmBroadcast && groupInfo != null && groupMember != null) { - val r = chatModel.controller.apiDeleteMemberChatItem( - chatRh, - groupId = groupInfo.groupId, - groupMemberId = groupMember.groupMemberId, - itemId = itemId - ) - deletedChatItem = r?.first - toChatItem = r?.second - } else { - val r = chatModel.controller.apiDeleteChatItem( - chatRh, - type = cInfo.chatType, - id = cInfo.apiId, - itemId = itemId, - mode = mode - ) - deletedChatItem = r?.deletedChatItem?.chatItem - toChatItem = r?.toChatItem?.chatItem - } - if (toChatItem == null && deletedChatItem != null) { - chatModel.removeChatItem(chatRh, cInfo, deletedChatItem) - } else if (toChatItem != null) { - chatModel.upsertChatItem(chatRh, cInfo, toChatItem) - } - } - }, - deleteMessages = { itemIds -> - if (itemIds.isNotEmpty()) { - val chatInfo = chat.chatInfo - withBGApi { - val deletedItems: ArrayList<ChatItem> = arrayListOf() - for (itemId in itemIds) { - val di = chatModel.controller.apiDeleteChatItem( - chatRh, chatInfo.chatType, chatInfo.apiId, itemId, CIDeleteMode.cidmInternal - )?.deletedChatItem?.chatItem - if (di != null) { - deletedItems.add(di) + ModalManager.end.showModalCloseable(true) { close -> + val chat = remember { activeChat }.value + if (chat?.chatInfo is ChatInfo.Direct) { + var contactInfo: Pair<ConnectionStats?, Profile?>? by remember { mutableStateOf(preloadedContactInfo) } + var code: String? by remember { mutableStateOf(preloadedCode) } + KeyChangeEffect(chat.id, ChatModel.networkStatuses.toMap()) { + contactInfo = chatModel.controller.apiContactInfo(chatRh, chat.chatInfo.apiId) + preloadedContactInfo = contactInfo + code = chatModel.controller.apiGetContactCode(chatRh, chat.chatInfo.apiId)?.second + preloadedCode = code + } + ChatInfoView(chatModel, (chat.chatInfo as ChatInfo.Direct).contact, contactInfo?.first, contactInfo?.second, chat.chatInfo.localAlias, code, close) + } else if (chat?.chatInfo is ChatInfo.Group) { + var link: Pair<String, GroupMemberRole>? by remember(chat.id) { mutableStateOf(preloadedLink) } + KeyChangeEffect(chat.id) { + setGroupMembers(chatRh, (chat.chatInfo as ChatInfo.Group).groupInfo, chatModel) + link = chatModel.controller.apiGetGroupLink(chatRh, chat.chatInfo.groupInfo.groupId) + preloadedLink = link + } + GroupChatInfoView(chatModel, chatRh, chat.id, link?.first, link?.second, { + link = it + preloadedLink = it + }, close) + } } } - for (di in deletedItems) { - chatModel.removeChatItem(chatRh, chatInfo, di) + }, + showMemberInfo = { groupInfo: GroupInfo, member: GroupMember -> + hideKeyboard(view) + withBGApi { + val r = chatModel.controller.apiGroupMemberInfo(chatRh, groupInfo.groupId, member.groupMemberId) + val stats = r?.second + val (_, code) = if (member.memberActive) { + val memCode = chatModel.controller.apiGetGroupMemberCode(chatRh, groupInfo.apiId, member.groupMemberId) + member to memCode?.second + } else { + member to null + } + setGroupMembers(chatRh, groupInfo, chatModel) + ModalManager.end.closeModals() + ModalManager.end.showModalCloseable(true) { close -> + remember { derivedStateOf { chatModel.getGroupMember(member.groupMemberId) } }.value?.let { mem -> + GroupMemberInfoView(chatRh, groupInfo, mem, stats, code, chatModel, close, close) + } + } } - } - } - }, - receiveFile = { fileId, encrypted -> - withApi { chatModel.controller.receiveFile(chatRh, user, fileId, encrypted) } - }, - cancelFile = { fileId -> - withApi { chatModel.controller.cancelFile(chatRh, user, fileId) } - }, - joinGroup = { groupId, onComplete -> - withApi { - chatModel.controller.apiJoinGroup(chatRh, groupId) - onComplete.invoke() - } - }, - startCall = out@ { media -> - withBGApi { - val cInfo = chat.chatInfo - if (cInfo is ChatInfo.Direct) { - chatModel.activeCall.value = Call(remoteHostId = chatRh, contact = cInfo.contact, callState = CallState.WaitCapabilities, localMedia = media) - chatModel.showCallView.value = true - chatModel.callCommand.add(WCallCommand.Capabilities(media)) - } - } - }, - endCall = { - val call = chatModel.activeCall.value - if (call != null) withApi { chatModel.callManager.endCall(call) } - }, - acceptCall = { contact -> - hideKeyboard(view) - val invitation = chatModel.callInvitations.remove(contact.id) - if (invitation == null) { - AlertManager.shared.showAlertMsg(generalGetString(MR.strings.call_already_ended)) - } else { - chatModel.callManager.acceptIncomingCall(invitation = invitation) - } - }, - acceptFeature = { contact, feature, param -> - withApi { - chatModel.controller.allowFeatureToContact(chatRh, contact, feature, param) - } - }, - openDirectChat = { contactId -> - withApi { - openDirectChat(chatRh, contactId, chatModel) - } - }, - updateContactStats = { contact -> - withApi { - val r = chatModel.controller.apiContactInfo(chatRh, chat.chatInfo.apiId) - if (r != null) { - val contactStats = r.first - if (contactStats != null) - chatModel.updateContactConnectionStats(chatRh, contact, contactStats) - } - } - }, - updateMemberStats = { groupInfo, member -> - withApi { - val r = chatModel.controller.apiGroupMemberInfo(chatRh, groupInfo.groupId, member.groupMemberId) - if (r != null) { - val memStats = r.second - if (memStats != null) { - chatModel.updateGroupMemberConnectionStats(chatRh, groupInfo, r.first, memStats) + }, + loadPrevMessages = { + if (chatModel.chatId.value != activeChat.value?.id) return@ChatLayout + val c = chatModel.getChat(chatModel.chatId.value ?: return@ChatLayout) + val firstId = chatModel.chatItems.firstOrNull()?.id + if (c != null && firstId != null) { + withBGApi { + Log.d(TAG, "TODOCHAT: loadPrevMessages: loading for ${c.id}, current chatId ${ChatModel.chatId.value}, size was ${ChatModel.chatItems.size}") + apiLoadPrevMessages(c, chatModel, firstId, searchText.value) + Log.d(TAG, "TODOCHAT: loadPrevMessages: loaded for ${c.id}, current chatId ${ChatModel.chatId.value}, size now ${ChatModel.chatItems.size}") + } } - } - } - }, - syncContactConnection = { contact -> - withApi { - val cStats = chatModel.controller.apiSyncContactRatchet(chatRh, contact.contactId, force = false) - if (cStats != null) { - chatModel.updateContactConnectionStats(chatRh, contact, cStats) - } - } - }, - syncMemberConnection = { groupInfo, member -> - withApi { - val r = chatModel.controller.apiSyncGroupMemberRatchet(chatRh, groupInfo.apiId, member.groupMemberId, force = false) - if (r != null) { - chatModel.updateGroupMemberConnectionStats(chatRh, groupInfo, r.first, r.second) - } - } - }, - findModelChat = { chatId -> - chatModel.getChat(chatId) - }, - findModelMember = { memberId -> - chatModel.groupMembers.find { it.id == memberId } - }, - setReaction = { cInfo, cItem, add, reaction -> - withApi { - val updatedCI = chatModel.controller.apiChatItemReaction( - rh = chatRh, - type = cInfo.chatType, - id = cInfo.apiId, - itemId = cItem.id, - add = add, - reaction = reaction - ) - if (updatedCI != null) { - chatModel.updateChatItem(cInfo, updatedCI) - } - } - }, - showItemDetails = { cInfo, cItem -> - withApi { - val ciInfo = chatModel.controller.apiGetChatItemInfo(chatRh, cInfo.chatType, cInfo.apiId, cItem.id) - if (ciInfo != null) { - if (chat.chatInfo is ChatInfo.Group) { - setGroupMembers(chatRh, chat.chatInfo.groupInfo, chatModel) + }, + deleteMessage = { itemId, mode -> + withBGApi { + val cInfo = chat.chatInfo + val toDeleteItem = chatModel.chatItems.firstOrNull { it.id == itemId } + val toModerate = toDeleteItem?.memberToModerate(chat.chatInfo) + val groupInfo = toModerate?.first + val groupMember = toModerate?.second + val deletedChatItem: ChatItem? + val toChatItem: ChatItem? + if (mode == CIDeleteMode.cidmBroadcast && groupInfo != null && groupMember != null) { + val r = chatModel.controller.apiDeleteMemberChatItem( + chatRh, + groupId = groupInfo.groupId, + groupMemberId = groupMember.groupMemberId, + itemId = itemId + ) + deletedChatItem = r?.first + toChatItem = r?.second + } else { + val r = chatModel.controller.apiDeleteChatItem( + chatRh, + type = cInfo.chatType, + id = cInfo.apiId, + itemId = itemId, + mode = mode + ) + deletedChatItem = r?.deletedChatItem?.chatItem + toChatItem = r?.toChatItem?.chatItem + } + if (toChatItem == null && deletedChatItem != null) { + chatModel.removeChatItem(chatRh, cInfo, deletedChatItem) + } else if (toChatItem != null) { + chatModel.upsertChatItem(chatRh, cInfo, toChatItem) + } } - ModalManager.end.closeModals() - ModalManager.end.showModal(endButtons = { ShareButton { - clipboard.shareText(itemInfoShareText(chatModel, cItem, ciInfo, chatModel.controller.appPrefs.developerTools.get())) - } }) { - ChatItemInfoView(chatModel, cItem, ciInfo, devTools = chatModel.controller.appPrefs.developerTools.get()) + }, + deleteMessages = { itemIds -> + if (itemIds.isNotEmpty()) { + val chatInfo = chat.chatInfo + withBGApi { + val deletedItems: ArrayList<ChatItem> = arrayListOf() + for (itemId in itemIds) { + val di = chatModel.controller.apiDeleteChatItem( + chatRh, chatInfo.chatType, chatInfo.apiId, itemId, CIDeleteMode.cidmInternal + )?.deletedChatItem?.chatItem + if (di != null) { + deletedItems.add(di) + } + } + for (di in deletedItems) { + chatModel.removeChatItem(chatRh, chatInfo, di) + } + } } - } - } - }, - addMembers = { groupInfo -> - hideKeyboard(view) - withApi { - setGroupMembers(chatRh, groupInfo, chatModel) + }, + receiveFile = { fileId -> + withBGApi { chatModel.controller.receiveFile(chatRh, user, fileId) } + }, + cancelFile = { fileId -> + withBGApi { chatModel.controller.cancelFile(chatRh, user, fileId) } + }, + joinGroup = { groupId, onComplete -> + withBGApi { + chatModel.controller.apiJoinGroup(chatRh, groupId) + onComplete.invoke() + } + }, + startCall = out@{ media -> + withBGApi { + val cInfo = chat.chatInfo + if (cInfo is ChatInfo.Direct) { + chatModel.activeCall.value = Call(remoteHostId = chatRh, contact = cInfo.contact, callState = CallState.WaitCapabilities, localMedia = media) + chatModel.showCallView.value = true + chatModel.callCommand.add(WCallCommand.Capabilities(media)) + } + } + }, + endCall = { + val call = chatModel.activeCall.value + if (call != null) withBGApi { chatModel.callManager.endCall(call) } + }, + acceptCall = { contact -> + hideKeyboard(view) + withBGApi { + val invitation = chatModel.callInvitations.remove(contact.id) + ?: controller.apiGetCallInvitations(chatModel.remoteHostId()).firstOrNull { it.contact.id == contact.id } + if (invitation == null) { + AlertManager.shared.showAlertMsg(generalGetString(MR.strings.call_already_ended)) + } else { + chatModel.callManager.acceptIncomingCall(invitation = invitation) + } + } + }, + acceptFeature = { contact, feature, param -> + withBGApi { + chatModel.controller.allowFeatureToContact(chatRh, contact, feature, param) + } + }, + openDirectChat = { contactId -> + withBGApi { + openDirectChat(chatRh, contactId, chatModel) + } + }, + updateContactStats = { contact -> + withBGApi { + val r = chatModel.controller.apiContactInfo(chatRh, chat.chatInfo.apiId) + if (r != null) { + val contactStats = r.first + if (contactStats != null) + chatModel.updateContactConnectionStats(chatRh, contact, contactStats) + } + } + }, + updateMemberStats = { groupInfo, member -> + withBGApi { + val r = chatModel.controller.apiGroupMemberInfo(chatRh, groupInfo.groupId, member.groupMemberId) + if (r != null) { + val memStats = r.second + if (memStats != null) { + chatModel.updateGroupMemberConnectionStats(chatRh, groupInfo, r.first, memStats) + } + } + } + }, + syncContactConnection = { contact -> + withBGApi { + val cStats = chatModel.controller.apiSyncContactRatchet(chatRh, contact.contactId, force = false) + if (cStats != null) { + chatModel.updateContactConnectionStats(chatRh, contact, cStats) + } + } + }, + syncMemberConnection = { groupInfo, member -> + withBGApi { + val r = chatModel.controller.apiSyncGroupMemberRatchet(chatRh, groupInfo.apiId, member.groupMemberId, force = false) + if (r != null) { + chatModel.updateGroupMemberConnectionStats(chatRh, groupInfo, r.first, r.second) + } + } + }, + findModelChat = { chatId -> + chatModel.getChat(chatId) + }, + findModelMember = { memberId -> + chatModel.groupMembers.find { it.id == memberId } + }, + setReaction = { cInfo, cItem, add, reaction -> + withBGApi { + val updatedCI = chatModel.controller.apiChatItemReaction( + rh = chatRh, + type = cInfo.chatType, + id = cInfo.apiId, + itemId = cItem.id, + add = add, + reaction = reaction + ) + if (updatedCI != null) { + chatModel.updateChatItem(cInfo, updatedCI) + } + } + }, + showItemDetails = { cInfo, cItem -> + withBGApi { + val ciInfo = chatModel.controller.apiGetChatItemInfo(chatRh, cInfo.chatType, cInfo.apiId, cItem.id) + if (ciInfo != null) { + if (chat.chatInfo is ChatInfo.Group) { + setGroupMembers(chatRh, chat.chatInfo.groupInfo, chatModel) + } + ModalManager.end.closeModals() + ModalManager.end.showModal(endButtons = { + ShareButton { + clipboard.shareText(itemInfoShareText(chatModel, cItem, ciInfo, chatModel.controller.appPrefs.developerTools.get())) + } + }) { + ChatItemInfoView(chatModel, cItem, ciInfo, devTools = chatModel.controller.appPrefs.developerTools.get()) + } + } + } + }, + addMembers = { groupInfo -> + hideKeyboard(view) + withBGApi { + setGroupMembers(chatRh, groupInfo, chatModel) + ModalManager.end.closeModals() + ModalManager.end.showModalCloseable(true) { close -> + AddGroupMembersView(chatRh, groupInfo, false, chatModel, close) + } + } + }, + openGroupLink = { groupInfo -> + hideKeyboard(view) + withBGApi { + val link = chatModel.controller.apiGetGroupLink(chatRh, groupInfo.groupId) + ModalManager.end.closeModals() + ModalManager.end.showModalCloseable(true) { + GroupLinkView(chatModel, chatRh, groupInfo, link?.first, link?.second, onGroupLinkUpdated = null) + } + } + }, + markRead = { range, unreadCountAfter -> + chatModel.markChatItemsRead(chat, range, unreadCountAfter) + ntfManager.cancelNotificationsForChat(chat.id) + withBGApi { + chatModel.controller.apiChatRead( + chatRh, + chat.chatInfo.chatType, + chat.chatInfo.apiId, + range + ) + } + }, + changeNtfsState = { enabled, currentValue -> toggleNotifications(chat, enabled, chatModel, currentValue) }, + onSearchValueChanged = { value -> + if (searchText.value == value) return@ChatLayout + if (chatModel.chatId.value != activeChat.value?.id) return@ChatLayout + val c = chatModel.getChat(chatModel.chatId.value ?: return@ChatLayout) ?: return@ChatLayout + withBGApi { + apiFindMessages(c, chatModel, value) + searchText.value = value + } + }, + onComposed, + developerTools = chatModel.controller.appPrefs.developerTools.get(), + ) + } + is ChatInfo.ContactConnection -> { + val close = { chatModel.chatId.value = null } + ModalView(close, showClose = appPlatform.isAndroid, content = { + ContactConnectionInfoView(chatModel, chat.remoteHostId, chat.chatInfo.contactConnection.connReqInv, chat.chatInfo.contactConnection, false, close) + }) + LaunchedEffect(chat.id) { + onComposed(chat.id) ModalManager.end.closeModals() - ModalManager.end.showModalCloseable(true) { close -> - AddGroupMembersView(chatRh, groupInfo, false, chatModel, close) - } + chatModel.chatItems.clear() } - }, - openGroupLink = { groupInfo -> - hideKeyboard(view) - withApi { - val link = chatModel.controller.apiGetGroupLink(chatRh, groupInfo.groupId) + } + is ChatInfo.InvalidJSON -> { + val close = { chatModel.chatId.value = null } + ModalView(close, showClose = appPlatform.isAndroid, content = { + InvalidJSONView(chat.chatInfo.json) + }) + LaunchedEffect(chat.id) { + onComposed(chat.id) ModalManager.end.closeModals() - ModalManager.end.showModalCloseable(true) { - GroupLinkView(chatModel, chatRh, groupInfo, link?.first, link?.second, onGroupLinkUpdated = null) - } + chatModel.chatItems.clear() } - }, - markRead = { range, unreadCountAfter -> - chatModel.markChatItemsRead(chat, range, unreadCountAfter) - ntfManager.cancelNotificationsForChat(chat.id) - withBGApi { - chatModel.controller.apiChatRead( - chatRh, - chat.chatInfo.chatType, - chat.chatInfo.apiId, - range - ) - } - }, - changeNtfsState = { enabled, currentValue -> toggleNotifications(chat, enabled, chatModel, currentValue) }, - onSearchValueChanged = { value -> - if (searchText.value == value) return@ChatLayout - if (chatModel.chatId.value != activeChat.value?.id) return@ChatLayout - val c = chatModel.getChat(chatModel.chatId.value ?: return@ChatLayout) ?: return@ChatLayout - withApi { - apiFindMessages(c, chatModel, value) - searchText.value = value - } - }, - onComposed, - developerTools = chatModel.controller.appPrefs.developerTools.get(), - ) + } + else -> {} + } } } @@ -472,7 +505,7 @@ fun ChatLayout( loadPrevMessages: () -> Unit, deleteMessage: (Long, CIDeleteMode) -> Unit, deleteMessages: (List<Long>) -> Unit, - receiveFile: (Long, Boolean) -> Unit, + receiveFile: (Long) -> Unit, cancelFile: (Long) -> Unit, joinGroup: (Long, () -> Unit) -> Unit, startCall: (CallMediaType) -> Unit, @@ -541,6 +574,8 @@ fun ChatLayout( bottomBar = composeView, modifier = Modifier.navigationBarsWithImePadding(), floatingActionButton = { floatingButton.value() }, + contentColor = LocalContentColor.current, + drawerContentColor = LocalContentColor.current, ) { contentPadding -> BoxWithConstraints(Modifier .fillMaxHeight() @@ -589,11 +624,27 @@ fun ChatInfoToolbar( val barButtons = arrayListOf<@Composable RowScope.() -> Unit>() val menuItems = arrayListOf<@Composable () -> Unit>() val activeCall by remember { chatModel.activeCall } - menuItems.add { - ItemAction(stringResource(MR.strings.search_verb), painterResource(MR.images.ic_search), onClick = { - showMenu.value = false - showSearch = true - }) + if (chat.chatInfo is ChatInfo.Local) { + barButtons.add { + IconButton({ + showMenu.value = false + showSearch = true + }, enabled = chat.chatInfo.noteFolder.ready + ) { + Icon( + painterResource(MR.images.ic_search), + stringResource(MR.strings.search_verb).capitalize(Locale.current), + tint = if (chat.chatInfo.noteFolder.ready) MaterialTheme.colors.primary else MaterialTheme.colors.secondary + ) + } + } + } else { + menuItems.add { + ItemAction(stringResource(MR.strings.search_verb), painterResource(MR.images.ic_search), onClick = { + showMenu.value = false + showSearch = true + }) + } } if (chat.chatInfo is ChatInfo.Direct && chat.chatInfo.contact.allowsFeature(ChatFeature.Calls)) { @@ -708,16 +759,18 @@ fun ChatInfoToolbar( } } - barButtons.add { - IconButton({ showMenu.value = true }) { - Icon(MoreVertFilled, stringResource(MR.strings.icon_descr_more_button), tint = MaterialTheme.colors.primary) + if (menuItems.isNotEmpty()) { + barButtons.add { + IconButton({ showMenu.value = true }) { + Icon(MoreVertFilled, stringResource(MR.strings.icon_descr_more_button), tint = MaterialTheme.colors.primary) + } } } DefaultTopAppBar( navigationButton = { if (appPlatform.isAndroid || showSearch) { NavigationButtonBack(onBackClicked) } }, title = { ChatInfoToolbarTitle(chat.chatInfo) }, - onTitleClick = info, + onTitleClick = if (chat.chatInfo is ChatInfo.Local) null else info, showSearch = showSearch, onSearchValueChanged = onSearchValueChanged, buttons = barButtons @@ -733,7 +786,7 @@ fun ChatInfoToolbar( } @Composable -fun ChatInfoToolbarTitle(cInfo: ChatInfo, imageSize: Dp = 40.dp, iconColor: Color = MaterialTheme.colors.secondaryVariant) { +fun ChatInfoToolbarTitle(cInfo: ChatInfo, imageSize: Dp = 40.dp, iconColor: Color = MaterialTheme.colors.secondaryVariant.mixWith(MaterialTheme.colors.onBackground, 0.97f)) { Row( horizontalArrangement = Arrangement.Center, verticalAlignment = Alignment.CenterVertically @@ -795,7 +848,7 @@ fun BoxWithConstraintsScope.ChatItemsList( loadPrevMessages: () -> Unit, deleteMessage: (Long, CIDeleteMode) -> Unit, deleteMessages: (List<Long>) -> Unit, - receiveFile: (Long, Boolean) -> Unit, + receiveFile: (Long) -> Unit, cancelFile: (Long) -> Unit, joinGroup: (Long, () -> Unit) -> Unit, acceptCall: (Contact) -> Unit, @@ -875,7 +928,7 @@ fun BoxWithConstraintsScope.ChatItemsList( if (dismissState.isAnimationRunning && (swipedToStart || swipedToEnd)) { LaunchedEffect(Unit) { scope.launch { - if (cItem.content is CIContent.SndMsgContent || cItem.content is CIContent.RcvMsgContent) { + if ((cItem.content is CIContent.SndMsgContent || cItem.content is CIContent.RcvMsgContent) && chat.chatInfo !is ChatInfo.Local) { if (composeState.value.editing) { composeState.value = ComposeState(contextItem = ComposeContextItem.QuotedItem(cItem), useLinkPreviews = useLinkPreviews) } else if (cItem.id != ChatItem.TEMP_LIVE_CHAT_ITEM_ID) { @@ -1309,7 +1362,7 @@ fun chatViewItemsRange(currIndex: Int?, prevHidden: Int?): IntRange? = sealed class ProviderMedia { data class Image(val data: ByteArray, val image: ImageBitmap): ProviderMedia() - data class Video(val uri: URI, val preview: String): ProviderMedia() + data class Video(val uri: URI, val fileSource: CryptoFile?, val preview: String): ProviderMedia() } private fun providerForGallery( @@ -1324,6 +1377,8 @@ private fun providerForGallery( fun item(skipInternalIndex: Int, initialChatId: Long): Pair<Int, ChatItem>? { var processedInternalIndex = -skipInternalIndex.sign val indexOfFirst = chatItems.indexOfFirst { it.id == initialChatId } + // The first was deleted or moderated + if (indexOfFirst == -1) return null for (chatItemsIndex in if (skipInternalIndex >= 0) indexOfFirst downTo 0 else indexOfFirst..chatItems.lastIndex) { val item = chatItems[chatItemsIndex] if (canShowMedia(item)) { @@ -1357,7 +1412,7 @@ private fun providerForGallery( val filePath = if (chatModel.connectedToRemote() && item.file?.loaded == true) getAppFilePath(item.file.fileName) else getLoadedFilePath(item.file) if (filePath != null) { val uri = getAppFileUri(filePath.substringAfterLast(File.separator)) - ProviderMedia.Video(uri, (item.content.msgContent as MsgContent.MCVideo).image) + ProviderMedia.Video(uri, item.file?.fileSource, (item.content.msgContent as MsgContent.MCVideo).image) } else null } else -> null @@ -1373,7 +1428,7 @@ private fun providerForGallery( override fun scrollToStart() { initialIndex = 0 - initialChatId = chatItems.first { canShowMedia(it) }.id + initialChatId = chatItems.firstOrNull { canShowMedia(it) }?.id ?: return } override fun onDismiss(index: Int) { @@ -1450,7 +1505,7 @@ fun PreviewChatLayout() { loadPrevMessages = {}, deleteMessage = { _, _ -> }, deleteMessages = { _ -> }, - receiveFile = { _, _ -> }, + receiveFile = { _ -> }, cancelFile = {}, joinGroup = { _, _ -> }, startCall = {}, @@ -1523,7 +1578,7 @@ fun PreviewGroupChatLayout() { loadPrevMessages = {}, deleteMessage = { _, _ -> }, deleteMessages = {}, - receiveFile = { _, _ -> }, + receiveFile = { _ -> }, cancelFile = {}, joinGroup = { _, _ -> }, startCall = {}, diff --git a/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/views/chat/ComposeView.kt b/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/views/chat/ComposeView.kt index b230d261f1..e5982d01db 100644 --- a/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/views/chat/ComposeView.kt +++ b/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/views/chat/ComposeView.kt @@ -267,7 +267,7 @@ fun ComposeView( fun loadLinkPreview(url: String, wait: Long? = null) { if (pendingLinkUrl.value == url) { composeState.value = composeState.value.copy(preview = ComposePreview.CLinkPreview(null)) - withApi { + withLongRunningApi(slow = 30_000, deadlock = 60_000) { if (wait != null) delay(wait) val lp = getLinkPreview(url) if (lp != null && pendingLinkUrl.value == url) { @@ -353,7 +353,10 @@ fun ComposeView( suspend fun send(chat: Chat, mc: MsgContent, quoted: Long?, file: CryptoFile? = null, live: Boolean = false, ttl: Int?): ChatItem? { val cInfo = chat.chatInfo - val aChatItem = chatModel.controller.apiSendMessage( + val aChatItem = if (chat.chatInfo.chatType == ChatType.Local) + chatModel.controller.apiCreateChatItem(rh = chat.remoteHostId, noteFolderId = chat.chatInfo.apiId, file = file, mc = mc) + else + chatModel.controller.apiSendMessage( rh = chat.remoteHostId, type = cInfo.chatType, id = cInfo.apiId, @@ -459,16 +462,15 @@ fun ComposeView( is ComposePreview.CLinkPreview -> msgs.add(checkLinkPreview()) is ComposePreview.MediaPreview -> { preview.content.forEachIndexed { index, it -> - val encrypted = chatController.appPrefs.privacyEncryptLocalFiles.get() val file = when (it) { is UploadContent.SimpleImage -> - if (remoteHost == null) saveImage(it.uri, encrypted = encrypted) + if (remoteHost == null) saveImage(it.uri) else desktopSaveImageInTmp(it.uri) is UploadContent.AnimatedImage -> - if (remoteHost == null) saveAnimImage(it.uri, encrypted = encrypted) + if (remoteHost == null) saveAnimImage(it.uri) else CryptoFile.desktopPlain(it.uri) is UploadContent.Video -> - if (remoteHost == null) saveFileFromUri(it.uri, encrypted = false) + if (remoteHost == null) saveFileFromUri(it.uri) else CryptoFile.desktopPlain(it.uri) } if (file != null) { @@ -506,7 +508,7 @@ fun ComposeView( } is ComposePreview.FilePreview -> { val file = if (remoteHost == null) { - saveFileFromUri(preview.uri, encrypted = chatController.appPrefs.privacyEncryptLocalFiles.get()) + saveFileFromUri(preview.uri) } else { CryptoFile.desktopPlain(preview.uri) } @@ -549,7 +551,7 @@ fun ComposeView( } fun sendMessage(ttl: Int?) { - withBGApi { + withLongRunningApi(slow = 30_000, deadlock = 60_000) { sendMessageAsync(null, false, ttl) } } @@ -575,7 +577,7 @@ fun ComposeView( fun allowVoiceToContact() { val contact = (chat.chatInfo as ChatInfo.Direct?)?.contact ?: return - withApi { + withBGApi { chatModel.controller.allowFeatureToContact(chat.remoteHostId, contact, ChatFeature.Voice) } } @@ -878,7 +880,7 @@ fun ComposeView( sendMessage(ttl) resetLinkPreview() }, - sendLiveMessage = ::sendLiveMessage, + sendLiveMessage = if (chat.chatInfo.chatType != ChatType.Local) ::sendLiveMessage else null, updateLiveMessage = ::updateLiveMessage, cancelLiveMessage = { composeState.value = composeState.value.copy(liveMessage = null) diff --git a/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/views/chat/ContactPreferences.kt b/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/views/chat/ContactPreferences.kt index c12982ada5..f412c02154 100644 --- a/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/views/chat/ContactPreferences.kt +++ b/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/views/chat/ContactPreferences.kt @@ -35,7 +35,7 @@ fun ContactPreferencesView( var currentFeaturesAllowed by rememberSaveable(ct, stateSaver = serializableSaver()) { mutableStateOf(featuresAllowed) } fun savePrefs(afterSave: () -> Unit = {}) { - withApi { + withBGApi { val prefs = contactFeaturesAllowedToPrefs(featuresAllowed) val toContact = m.controller.apiSetContactPrefs(rhId, ct.contactId, prefs) if (toContact != null) { diff --git a/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/views/chat/ContextItemView.kt b/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/views/chat/ContextItemView.kt index 49203c7cfb..b53574cfa4 100644 --- a/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/views/chat/ContextItemView.kt +++ b/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/views/chat/ContextItemView.kt @@ -34,6 +34,7 @@ fun ContextItemView( fun msgContentView(lines: Int) { MarkdownText( contextItem.text, contextItem.formattedText, + toggleSecrets = false, maxLines = lines, linkMode = SimplexLinkMode.DESCRIPTION, modifier = Modifier.fillMaxWidth(), diff --git a/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/views/chat/ScanCodeView.kt b/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/views/chat/ScanCodeView.kt index bb479d8eb3..73017c3d42 100644 --- a/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/views/chat/ScanCodeView.kt +++ b/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/views/chat/ScanCodeView.kt @@ -13,29 +13,20 @@ import dev.icerock.moko.resources.compose.stringResource @Composable fun ScanCodeView(verifyCode: (String?, cb: (Boolean) -> Unit) -> Unit, close: () -> Unit) { Column( - Modifier - .fillMaxSize() - .padding(horizontal = DEFAULT_PADDING) + Modifier.fillMaxSize() ) { - AppBarTitle(stringResource(MR.strings.scan_code), withPadding = false) - Box( - Modifier - .fillMaxWidth() - .aspectRatio(ratio = 1F) - .padding(bottom = DEFAULT_PADDING) - ) { - QRCodeScanner { text -> - verifyCode(text) { - if (it) { - close() - } else { - AlertManager.shared.showAlertMsg( - title = generalGetString(MR.strings.incorrect_code) - ) - } + AppBarTitle(stringResource(MR.strings.scan_code)) + QRCodeScanner { text -> + verifyCode(text) { + if (it) { + close() + } else { + AlertManager.shared.showAlertMsg( + title = generalGetString(MR.strings.incorrect_code) + ) } } } - Text(stringResource(MR.strings.scan_code_from_contacts_app)) + Text(stringResource(MR.strings.scan_code_from_contacts_app), Modifier.padding(horizontal = DEFAULT_PADDING)) } } diff --git a/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/views/chat/SendMsgView.kt b/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/views/chat/SendMsgView.kt index e566cf30d3..f1079d2f5f 100644 --- a/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/views/chat/SendMsgView.kt +++ b/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/views/chat/SendMsgView.kt @@ -258,7 +258,8 @@ private fun CustomDisappearingMessageDialog( DefaultDialog(onDismissRequest = { setShowDialog(false) }) { Surface( - shape = RoundedCornerShape(corner = CornerSize(25.dp)) + shape = RoundedCornerShape(corner = CornerSize(25.dp)), + contentColor = LocalContentColor.current ) { Box( contentAlignment = Alignment.Center diff --git a/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/views/chat/VerifyCodeView.kt b/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/views/chat/VerifyCodeView.kt index e1840dd885..57c469adf2 100644 --- a/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/views/chat/VerifyCodeView.kt +++ b/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/views/chat/VerifyCodeView.kt @@ -74,9 +74,7 @@ private fun VerifyCodeLayout( } } - SectionView { - QRCode(connectionCode, Modifier.aspectRatio(1f)) - } + QRCode(connectionCode, padding = PaddingValues(vertical = DEFAULT_PADDING_HALF)) Row(Modifier.fillMaxWidth(), verticalAlignment = Alignment.CenterVertically) { Spacer(Modifier.weight(2f)) diff --git a/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/views/chat/group/AddGroupMembersView.kt b/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/views/chat/group/AddGroupMembersView.kt index 37ee9729f5..e4f31748cc 100644 --- a/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/views/chat/group/AddGroupMembersView.kt +++ b/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/views/chat/group/AddGroupMembersView.kt @@ -54,7 +54,7 @@ fun AddGroupMembersView(rhId: Long?, groupInfo: GroupInfo, creatingGroup: Boolea }, inviteMembers = { allowModifyMembers = false - withApi { + withLongRunningApi(slow = 30_000, deadlock = 60_000) { for (contactId in selectedContacts) { val member = chatModel.controller.apiAddMember(rhId, groupInfo.groupId, contactId, selectedRole.value) if (member != null) { @@ -68,7 +68,7 @@ fun AddGroupMembersView(rhId: Long?, groupInfo: GroupInfo, creatingGroup: Boolea }, clearSelection = { selectedContacts.clear() }, addContact = { contactId -> if (contactId !in selectedContacts) selectedContacts.add(contactId) }, - removeContact = { contactId -> selectedContacts.removeIf { it == contactId } }, + removeContact = { contactId -> selectedContacts.removeAll { it == contactId } }, close = close, ) KeyChangeEffect(chatModel.chatId.value) { diff --git a/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/views/chat/group/GroupChatInfoView.kt b/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/views/chat/group/GroupChatInfoView.kt index d3b1841fe0..d602d78d89 100644 --- a/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/views/chat/group/GroupChatInfoView.kt +++ b/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/views/chat/group/GroupChatInfoView.kt @@ -56,11 +56,9 @@ fun GroupChatInfoView(chatModel: ChatModel, rhId: Long?, chatId: String, groupLi currentUser, sendReceipts = sendReceipts, setSendReceipts = { sendRcpts -> - withApi { - val chatSettings = (chat.chatInfo.chatSettings ?: ChatSettings.defaults).copy(sendRcpts = sendRcpts.bool) - updateChatSettings(chat, chatSettings, chatModel) - sendReceipts.value = sendRcpts - } + val chatSettings = (chat.chatInfo.chatSettings ?: ChatSettings.defaults).copy(sendRcpts = sendRcpts.bool) + updateChatSettings(chat, chatSettings, chatModel) + sendReceipts.value = sendRcpts }, members = chatModel.groupMembers .filter { it.memberStatus != GroupMemberStatus.MemLeft && it.memberStatus != GroupMemberStatus.MemRemoved } @@ -68,7 +66,7 @@ fun GroupChatInfoView(chatModel: ChatModel, rhId: Long?, chatId: String, groupLi developerTools, groupLink, addMembers = { - withApi { + withBGApi { setGroupMembers(rhId, groupInfo, chatModel) ModalManager.end.showModalCloseable(true) { close -> AddGroupMembersView(rhId, groupInfo, false, chatModel, close) @@ -76,7 +74,7 @@ fun GroupChatInfoView(chatModel: ChatModel, rhId: Long?, chatId: String, groupLi } }, showMemberInfo = { member -> - withApi { + withBGApi { val r = chatModel.controller.apiGroupMemberInfo(rhId, groupInfo.groupId, member.groupMemberId) val stats = r?.second val (_, code) = if (member.memberActive) { @@ -112,7 +110,7 @@ fun GroupChatInfoView(chatModel: ChatModel, rhId: Long?, chatId: String, groupLi } }, deleteGroup = { deleteGroupDialog(chat, groupInfo, chatModel, close) }, - clearChat = { clearChatDialog(chat, chatModel, close) }, + clearChat = { clearChatDialog(chat, close) }, leaveGroup = { leaveGroupDialog(rhId, groupInfo, chatModel, close) }, manageGroupLink = { ModalManager.end.showModal { GroupLinkView(chatModel, rhId, groupInfo, groupLink, groupLinkMemberRole, onGroupLinkUpdated) } @@ -131,7 +129,7 @@ fun deleteGroupDialog(chat: Chat, groupInfo: GroupInfo, chatModel: ChatModel, cl text = generalGetString(alertTextKey), confirmText = generalGetString(MR.strings.delete_verb), onConfirm = { - withApi { + withBGApi { val r = chatModel.controller.apiDeleteChat(chat.remoteHostId, chatInfo.chatType, chatInfo.apiId) if (r) { chatModel.removeChat(chat.remoteHostId, chatInfo.id) @@ -154,7 +152,7 @@ fun leaveGroupDialog(rhId: Long?, groupInfo: GroupInfo, chatModel: ChatModel, cl text = generalGetString(MR.strings.you_will_stop_receiving_messages_from_this_group_chat_history_will_be_preserved), confirmText = generalGetString(MR.strings.leave_group_button), onConfirm = { - withApi { + withBGApi { chatModel.controller.leaveGroup(rhId, groupInfo.groupId) close?.invoke() } @@ -169,7 +167,7 @@ private fun removeMemberAlert(rhId: Long?, groupInfo: GroupInfo, mem: GroupMembe text = generalGetString(MR.strings.member_will_be_removed_from_group_cannot_be_undone), confirmText = generalGetString(MR.strings.remove_member_confirmation), onConfirm = { - withApi { + withBGApi { val updatedMember = chatModel.controller.apiRemoveMember(rhId, groupInfo.groupId, mem.groupMemberId) if (updatedMember != null) { chatModel.upsertGroupMember(rhId, groupInfo, updatedMember) @@ -370,6 +368,18 @@ private fun AddMembersButton(tint: Color = MaterialTheme.colors.primary, onClick @Composable private fun MemberRow(member: GroupMember, user: Boolean = false, onClick: (() -> Unit)? = null) { + @Composable + fun MemberInfo() { + if (member.blocked) { + Text(stringResource(MR.strings.member_info_member_blocked), color = MaterialTheme.colors.secondary) + } else { + val role = member.memberRole + if (role in listOf(GroupMemberRole.Owner, GroupMemberRole.Admin, GroupMemberRole.Observer)) { + Text(role.text, color = MaterialTheme.colors.secondary) + } + } + } + Row( Modifier.fillMaxWidth(), horizontalArrangement = Arrangement.SpaceBetween, @@ -403,10 +413,7 @@ private fun MemberRow(member: GroupMember, user: Boolean = false, onClick: (() - ) } } - val role = member.memberRole - if (role == GroupMemberRole.Owner || role == GroupMemberRole.Admin) { - Text(role.text, color = MaterialTheme.colors.secondary) - } + MemberInfo() } } @@ -417,6 +424,7 @@ private fun MemberVerifiedShield() { @Composable private fun DropDownMenuForMember(rhId: Long?, member: GroupMember, groupInfo: GroupInfo, showMenu: MutableState<Boolean>) { + // revert from this: DefaultDropdownMenu(showMenu) { if (member.canBeRemoved(groupInfo)) { ItemAction(stringResource(MR.strings.remove_member_button), painterResource(MR.images.ic_delete), color = MaterialTheme.colors.error, onClick = { @@ -436,6 +444,49 @@ private fun DropDownMenuForMember(rhId: Long?, member: GroupMember, groupInfo: G }) } } + // revert to this: vvv +// if (groupInfo.membership.memberRole >= GroupMemberRole.Admin) { +// val canBlockForAll = member.canBlockForAll(groupInfo) +// val canRemove = member.canBeRemoved(groupInfo) +// if (canBlockForAll || canRemove) { +// DefaultDropdownMenu(showMenu) { +// if (canBlockForAll) { +// if (member.blockedByAdmin) { +// ItemAction(stringResource(MR.strings.unblock_for_all), painterResource(MR.images.ic_do_not_touch), onClick = { +// unblockForAllAlert(rhId, groupInfo, member) +// showMenu.value = false +// }) +// } else { +// ItemAction(stringResource(MR.strings.block_for_all), painterResource(MR.images.ic_back_hand), color = MaterialTheme.colors.error, onClick = { +// blockForAllAlert(rhId, groupInfo, member) +// showMenu.value = false +// }) +// } +// } +// if (canRemove) { +// ItemAction(stringResource(MR.strings.remove_member_button), painterResource(MR.images.ic_delete), color = MaterialTheme.colors.error, onClick = { +// removeMemberAlert(rhId, groupInfo, member) +// showMenu.value = false +// }) +// } +// } +// } +// } else if (!member.blockedByAdmin) { +// DefaultDropdownMenu(showMenu) { +// if (member.memberSettings.showMessages) { +// ItemAction(stringResource(MR.strings.block_member_button), painterResource(MR.images.ic_back_hand), color = MaterialTheme.colors.error, onClick = { +// blockMemberAlert(rhId, groupInfo, member) +// showMenu.value = false +// }) +// } else { +// ItemAction(stringResource(MR.strings.unblock_member_button), painterResource(MR.images.ic_do_not_touch), onClick = { +// unblockMemberAlert(rhId, groupInfo, member) +// showMenu.value = false +// }) +// } +// } +// } + // ^^^ } @Composable diff --git a/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/views/chat/group/GroupLinkView.kt b/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/views/chat/group/GroupLinkView.kt index 02ce90243c..7b198bc41a 100644 --- a/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/views/chat/group/GroupLinkView.kt +++ b/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/views/chat/group/GroupLinkView.kt @@ -38,7 +38,7 @@ fun GroupLinkView( var creatingLink by rememberSaveable { mutableStateOf(false) } fun createLink() { creatingLink = true - withApi { + withBGApi { val link = chatModel.controller.apiCreateGroupLink(rhId, groupInfo.groupId) if (link != null) { groupLink = link.first @@ -78,7 +78,7 @@ fun GroupLinkView( text = generalGetString(MR.strings.all_group_members_will_remain_connected), confirmText = generalGetString(MR.strings.delete_verb), onConfirm = { - withApi { + withBGApi { val r = chatModel.controller.apiDeleteGroupLink(rhId, groupInfo.groupId) if (r) { groupLink = null @@ -153,7 +153,7 @@ fun GroupLinkLayout( } initialLaunch = false } - SimpleXLinkQRCode(groupLink, Modifier.aspectRatio(1f).padding(horizontal = DEFAULT_PADDING)) + SimpleXLinkQRCode(groupLink) Row( horizontalArrangement = Arrangement.spacedBy(10.dp), verticalAlignment = Alignment.CenterVertically, diff --git a/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/views/chat/group/GroupMemberInfoView.kt b/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/views/chat/group/GroupMemberInfoView.kt index 00b236c7dd..54614d0227 100644 --- a/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/views/chat/group/GroupMemberInfoView.kt +++ b/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/views/chat/group/GroupMemberInfoView.kt @@ -3,9 +3,11 @@ package chat.simplex.common.views.chat.group import InfoRow import SectionBottomSpacer import SectionDividerSpaced +import SectionItemView import SectionSpacer import SectionTextFooter import SectionView +import TextIconSpaced import androidx.compose.desktop.ui.tooling.preview.Preview import java.net.URI import androidx.compose.foundation.* @@ -66,7 +68,7 @@ fun GroupMemberInfoView( connectionCode, getContactChat = { chatModel.getContactChat(it) }, openDirectChat = { - withApi { + withBGApi { val c = chatModel.controller.apiGetChat(rhId, ChatType.Direct, it) if (c != null) { if (chatModel.getContactChat(it) == null) { @@ -81,7 +83,7 @@ fun GroupMemberInfoView( } }, createMemberContact = { - withApi { + withBGApi { progressIndicator = true val memberContact = chatModel.controller.apiCreateMemberContact(rhId, groupInfo.apiId, member.groupMemberId) if (memberContact != null) { @@ -99,6 +101,8 @@ fun GroupMemberInfoView( }, blockMember = { blockMemberAlert(rhId, groupInfo, member) }, unblockMember = { unblockMemberAlert(rhId, groupInfo, member) }, + blockForAll = { blockForAllAlert(rhId, groupInfo, member) }, + unblockForAll = { unblockForAllAlert(rhId, groupInfo, member) }, removeMember = { removeMemberDialog(rhId, groupInfo, member, chatModel, close) }, onRoleSelected = { if (it == newRole.value) return@GroupMemberInfoLayout @@ -107,7 +111,7 @@ fun GroupMemberInfoView( updateMemberRoleDialog(it, member, onDismiss = { newRole.value = prevValue }) { - withApi { + withBGApi { kotlin.runCatching { val mem = chatModel.controller.apiMemberRole(rhId, groupInfo.groupId, member.groupMemberId, it) chatModel.upsertGroupMember(rhId, groupInfo, mem) @@ -119,7 +123,7 @@ fun GroupMemberInfoView( }, switchMemberAddress = { showSwitchAddressAlert(switchAddress = { - withApi { + withBGApi { val r = chatModel.controller.apiSwitchGroupMember(rhId, groupInfo.apiId, member.groupMemberId) if (r != null) { connStats.value = r.second @@ -131,7 +135,7 @@ fun GroupMemberInfoView( }, abortSwitchMemberAddress = { showAbortSwitchAddressAlert(abortSwitchAddress = { - withApi { + withBGApi { val r = chatModel.controller.apiAbortSwitchGroupMember(rhId, groupInfo.apiId, member.groupMemberId) if (r != null) { connStats.value = r.second @@ -142,7 +146,7 @@ fun GroupMemberInfoView( }) }, syncMemberConnection = { - withApi { + withBGApi { val r = chatModel.controller.apiSyncGroupMemberRatchet(rhId, groupInfo.apiId, member.groupMemberId, force = false) if (r != null) { connStats.value = r.second @@ -153,7 +157,7 @@ fun GroupMemberInfoView( }, syncMemberConnectionForce = { showSyncConnectionForceAlert(syncConnectionForce = { - withApi { + withBGApi { val r = chatModel.controller.apiSyncGroupMemberRatchet(rhId, groupInfo.apiId, member.groupMemberId, force = true) if (r != null) { connStats.value = r.second @@ -204,7 +208,7 @@ fun removeMemberDialog(rhId: Long?, groupInfo: GroupInfo, member: GroupMember, c text = generalGetString(MR.strings.member_will_be_removed_from_group_cannot_be_undone), confirmText = generalGetString(MR.strings.remove_member_confirmation), onConfirm = { - withApi { + withBGApi { val removedMember = chatModel.controller.apiRemoveMember(rhId, member.groupId, member.groupMemberId) if (removedMember != null) { chatModel.upsertGroupMember(rhId, groupInfo, removedMember) @@ -230,6 +234,8 @@ fun GroupMemberInfoLayout( connectViaAddress: (String) -> Unit, blockMember: () -> Unit, unblockMember: () -> Unit, + blockForAll: () -> Unit, + unblockForAll: () -> Unit, removeMember: () -> Unit, onRoleSelected: (GroupMemberRole) -> Unit, switchMemberAddress: () -> Unit, @@ -248,6 +254,46 @@ fun GroupMemberInfoLayout( } } + @Composable + fun AdminDestructiveSection() { + val canBlockForAll = member.canBlockForAll(groupInfo) + val canRemove = member.canBeRemoved(groupInfo) + if (canBlockForAll || canRemove) { + SectionDividerSpaced(maxBottomPadding = false) + SectionView { + if (canBlockForAll) { + if (member.blockedByAdmin) { + UnblockForAllButton(unblockForAll) + } else { + BlockForAllButton(blockForAll) + } + } + if (canRemove) { + RemoveMemberButton(removeMember) + } + } + } + } + + @Composable + fun NonAdminBlockSection() { + SectionDividerSpaced(maxBottomPadding = false) + SectionView { + if (member.blockedByAdmin) { + SettingsActionItem( + painterResource(MR.images.ic_back_hand), + stringResource(MR.strings.member_blocked_by_admin), + click = null, + disabled = true + ) + } else if (member.memberSettings.showMessages) { + BlockMemberButton(blockMember) + } else { + UnblockMemberButton(unblockMember) + } + } + } + Column( Modifier .fillMaxWidth() @@ -289,7 +335,7 @@ fun GroupMemberInfoLayout( if (member.contactLink != null) { SectionView(stringResource(MR.strings.address_section_title).uppercase()) { - SimpleXLinkQRCode(member.contactLink, Modifier.padding(horizontal = DEFAULT_PADDING, vertical = DEFAULT_PADDING_HALF).aspectRatio(1f)) + SimpleXLinkQRCode(member.contactLink) val clipboard = LocalClipboardManager.current ShareAddressButton { clipboard.shareText(simplexChatLink(member.contactLink)) } if (contactId != null) { @@ -344,6 +390,7 @@ fun GroupMemberInfoLayout( } } + // revert from this: SectionDividerSpaced(maxBottomPadding = false) SectionView { if (member.memberSettings.showMessages) { @@ -355,6 +402,13 @@ fun GroupMemberInfoLayout( RemoveMemberButton(removeMember) } } + // revert to this: vvv +// if (groupInfo.membership.memberRole >= GroupMemberRole.Admin) { +// AdminDestructiveSection() +// } else { +// NonAdminBlockSection() +// } + // ^^^ if (developerTools) { SectionDividerSpaced() @@ -370,7 +424,7 @@ fun GroupMemberInfoLayout( @Composable fun GroupMemberInfoHeader(member: GroupMember) { Column( - Modifier.padding(horizontal = 8.dp), + Modifier.padding(horizontal = 16.dp), horizontalAlignment = Alignment.CenterHorizontally ) { ProfileImage(size = 192.dp, member.image, color = if (isInDarkTheme()) GroupDark else SettingsSecondaryLight) @@ -427,6 +481,26 @@ fun UnblockMemberButton(onClick: () -> Unit) { ) } +@Composable +fun BlockForAllButton(onClick: () -> Unit) { + SettingsActionItem( + painterResource(MR.images.ic_back_hand), + stringResource(MR.strings.block_for_all), + click = onClick, + textColor = Color.Red, + iconColor = Color.Red, + ) +} + +@Composable +fun UnblockForAllButton(onClick: () -> Unit) { + SettingsActionItem( + painterResource(MR.images.ic_do_not_touch), + stringResource(MR.strings.unblock_for_all), + click = onClick + ) +} + @Composable fun RemoveMemberButton(onClick: () -> Unit) { SettingsActionItem( @@ -505,8 +579,8 @@ private fun updateMemberRoleDialog( fun connectViaMemberAddressAlert(rhId: Long?, connReqUri: String) { try { val uri = URI(connReqUri) - withApi { - planAndConnect(chatModel, rhId, uri, incognito = null, close = { ModalManager.closeAllModalsEverywhere() }) + withBGApi { + planAndConnect(rhId, uri, incognito = null, close = { ModalManager.closeAllModalsEverywhere() }) } } catch (e: RuntimeException) { AlertManager.shared.showAlertMsg( @@ -553,6 +627,36 @@ fun updateMemberSettings(rhId: Long?, gInfo: GroupInfo, member: GroupMember, mem } } +fun blockForAllAlert(rhId: Long?, gInfo: GroupInfo, mem: GroupMember) { + AlertManager.shared.showAlertDialog( + title = generalGetString(MR.strings.block_for_all_question), + text = generalGetString(MR.strings.block_member_desc).format(mem.chatViewName), + confirmText = generalGetString(MR.strings.block_for_all), + onConfirm = { + blockMemberForAll(rhId, gInfo, mem, true) + }, + destructive = true, + ) +} + +fun unblockForAllAlert(rhId: Long?, gInfo: GroupInfo, mem: GroupMember) { + AlertManager.shared.showAlertDialog( + title = generalGetString(MR.strings.unblock_for_all_question), + text = generalGetString(MR.strings.unblock_member_desc).format(mem.chatViewName), + confirmText = generalGetString(MR.strings.unblock_for_all), + onConfirm = { + blockMemberForAll(rhId, gInfo, mem, false) + }, + ) +} + +fun blockMemberForAll(rhId: Long?, gInfo: GroupInfo, member: GroupMember, blocked: Boolean) { + withBGApi { + val updatedMember = ChatController.apiBlockMemberForAll(rhId, gInfo.groupId, member.groupMemberId, blocked) + chatModel.upsertGroupMember(rhId, gInfo, updatedMember) + } +} + @Preview @Composable fun PreviewGroupMemberInfoLayout() { @@ -570,6 +674,8 @@ fun PreviewGroupMemberInfoLayout() { connectViaAddress = {}, blockMember = {}, unblockMember = {}, + blockForAll = {}, + unblockForAll = {}, removeMember = {}, onRoleSelected = {}, switchMemberAddress = {}, diff --git a/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/views/chat/group/GroupPreferences.kt b/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/views/chat/group/GroupPreferences.kt index 3cdfaad2d9..694dac8898 100644 --- a/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/views/chat/group/GroupPreferences.kt +++ b/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/views/chat/group/GroupPreferences.kt @@ -32,7 +32,7 @@ fun GroupPreferencesView(m: ChatModel, rhId: Long?, chatId: String, close: () -> var currentPreferences by rememberSaveable(gInfo, stateSaver = serializableSaver()) { mutableStateOf(preferences) } fun savePrefs(afterSave: () -> Unit = {}) { - withApi { + withBGApi { val gp = gInfo.groupProfile.copy(groupPreferences = preferences.toGroupPreferences()) val g = m.controller.apiUpdateGroup(rhId, gInfo.groupId, gp) if (g != null) { @@ -112,6 +112,11 @@ private fun GroupPreferencesLayout( FeatureSection(GroupFeature.Files, allowFiles, groupInfo, preferences, onTTLUpdated) { applyPrefs(preferences.copy(files = GroupPreference(enable = it))) } + SectionDividerSpaced(true, maxBottomPadding = false) + val enableHistory = remember(preferences) { mutableStateOf(preferences.history.enable) } + FeatureSection(GroupFeature.History, enableHistory, groupInfo, preferences, onTTLUpdated) { + applyPrefs(preferences.copy(history = GroupPreference(enable = it))) + } if (groupInfo.canEdit) { SectionDividerSpaced(maxTopPadding = true, maxBottomPadding = false) ResetSaveButtons( diff --git a/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/views/chat/group/GroupProfileView.kt b/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/views/chat/group/GroupProfileView.kt index f92fd88dc0..35bec31d7b 100644 --- a/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/views/chat/group/GroupProfileView.kt +++ b/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/views/chat/group/GroupProfileView.kt @@ -35,7 +35,7 @@ fun GroupProfileView(rhId: Long?, groupInfo: GroupInfo, chatModel: ChatModel, cl close = close, groupProfile = groupInfo.groupProfile, saveProfile = { p -> - withApi { + withBGApi { val gInfo = chatModel.controller.apiUpdateGroup(rhId, groupInfo.groupId, p) if (gInfo != null) { chatModel.updateGroup(rhId, gInfo) diff --git a/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/views/chat/group/WelcomeMessageView.kt b/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/views/chat/group/WelcomeMessageView.kt index 577c19648d..9124eed4c3 100644 --- a/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/views/chat/group/WelcomeMessageView.kt +++ b/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/views/chat/group/WelcomeMessageView.kt @@ -15,6 +15,7 @@ import androidx.compose.runtime.saveable.rememberSaveable import androidx.compose.ui.Modifier import androidx.compose.ui.focus.FocusRequester import androidx.compose.ui.platform.LocalClipboardManager +import androidx.compose.ui.platform.LocalUriHandler import androidx.compose.ui.text.AnnotatedString import dev.icerock.moko.resources.compose.painterResource import dev.icerock.moko.resources.compose.stringResource @@ -35,7 +36,7 @@ fun GroupWelcomeView(m: ChatModel, rhId: Long?, groupInfo: GroupInfo, close: () val welcomeText = remember { mutableStateOf(gInfo.groupProfile.description ?: "") } fun save(afterSave: () -> Unit = {}) { - withApi { + withBGApi { var welcome: String? = welcomeText.value.trim('\n', ' ') if (welcome?.length == 0) { welcome = null @@ -119,13 +120,15 @@ private fun GroupWelcomeLayout( @Composable private fun TextPreview(text: String, linkMode: SimplexLinkMode, markdown: Boolean = true) { + val uriHandler = LocalUriHandler.current Column { SelectionContainer(Modifier.fillMaxWidth()) { MarkdownText( text, formattedText = if (markdown) remember(text) { parseToMarkdown(text) } else null, + toggleSecrets = false, modifier = Modifier.fillMaxHeight().padding(horizontal = DEFAULT_PADDING), - linkMode = linkMode, + linkMode = linkMode, uriHandler = uriHandler, style = MaterialTheme.typography.body1.copy(color = MaterialTheme.colors.onBackground, lineHeight = 22.sp) ) } diff --git a/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/views/chat/item/CIFileView.kt b/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/views/chat/item/CIFileView.kt index 0d439f1235..6a1db9249e 100644 --- a/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/views/chat/item/CIFileView.kt +++ b/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/views/chat/item/CIFileView.kt @@ -28,7 +28,7 @@ import java.net.URI fun CIFileView( file: CIFile?, edited: Boolean, - receiveFile: (Long, Boolean) -> Unit + receiveFile: (Long) -> Unit ) { val saveFileLauncher = rememberSaveFileLauncher(ciFile = file) @@ -68,11 +68,10 @@ fun CIFileView( fun fileAction() { if (file != null) { - when (file.fileStatus) { - is CIFileStatus.RcvInvitation -> { + when { + file.fileStatus is CIFileStatus.RcvInvitation -> { if (fileSizeValid()) { - val encrypted = chatController.appPrefs.privacyEncryptLocalFiles.get() - receiveFile(file.fileId, encrypted) + receiveFile(file.fileId) } else { AlertManager.shared.showAlertMsg( generalGetString(MR.strings.large_file), @@ -80,7 +79,7 @@ fun CIFileView( ) } } - is CIFileStatus.RcvAccepted -> + file.fileStatus is CIFileStatus.RcvAccepted -> when (file.fileProtocol) { FileProtocol.XFTP -> AlertManager.shared.showAlertMsg( @@ -92,16 +91,17 @@ fun CIFileView( generalGetString(MR.strings.waiting_for_file), generalGetString(MR.strings.file_will_be_received_when_contact_is_online) ) + FileProtocol.LOCAL -> {} } - is CIFileStatus.RcvComplete -> { - withBGApi { + file.fileStatus is CIFileStatus.RcvComplete || (file.fileStatus is CIFileStatus.SndStored && file.fileProtocol == FileProtocol.LOCAL) -> { + withLongRunningApi(slow = 60_000, deadlock = 600_000) { var filePath = getLoadedFilePath(file) if (chatModel.connectedToRemote() && filePath == null) { file.loadRemoteFile(true) filePath = getLoadedFilePath(file) } if (filePath != null) { - withApi { + withLongRunningApi { saveFileLauncher.launch(file.fileName) } } else { @@ -131,7 +131,8 @@ fun CIFileView( Surface( Modifier.drawRingModifier(angle, strokeColor, strokeWidth), color = Color.Transparent, - shape = MaterialTheme.shapes.small.copy(CornerSize(percent = 50)) + shape = MaterialTheme.shapes.small.copy(CornerSize(percent = 50)), + contentColor = LocalContentColor.current ) { Box(Modifier.size(32.dp)) } @@ -152,11 +153,13 @@ fun CIFileView( when (file.fileProtocol) { FileProtocol.XFTP -> progressIndicator() FileProtocol.SMP -> fileIcon() + FileProtocol.LOCAL -> fileIcon() } is CIFileStatus.SndTransfer -> when (file.fileProtocol) { FileProtocol.XFTP -> progressCircle(file.fileStatus.sndProgress, file.fileStatus.sndTotal) FileProtocol.SMP -> progressIndicator() + FileProtocol.LOCAL -> {} } is CIFileStatus.SndComplete -> fileIcon(innerIcon = painterResource(MR.images.ic_check_filled)) is CIFileStatus.SndCancelled -> fileIcon(innerIcon = painterResource(MR.images.ic_close)) diff --git a/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/views/chat/item/CIGroupInvitationView.kt b/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/views/chat/item/CIGroupInvitationView.kt index 56dd7a360a..911bbaf833 100644 --- a/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/views/chat/item/CIGroupInvitationView.kt +++ b/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/views/chat/item/CIGroupInvitationView.kt @@ -88,6 +88,7 @@ fun CIGroupInvitationView( }) else Modifier, shape = RoundedCornerShape(18.dp), color = if (sent) sentColor else receivedColor, + contentColor = LocalContentColor.current ) { Box( Modifier diff --git a/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/views/chat/item/CIImageView.kt b/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/views/chat/item/CIImageView.kt index 1e5919c0b6..5aed7742bc 100644 --- a/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/views/chat/item/CIImageView.kt +++ b/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/views/chat/item/CIImageView.kt @@ -32,11 +32,10 @@ import java.net.URI fun CIImageView( image: String, file: CIFile?, - encryptLocalFile: Boolean, metaColor: Color, imageProvider: () -> ImageGalleryProvider, showMenu: MutableState<Boolean>, - receiveFile: (Long, Boolean) -> Unit + receiveFile: (Long) -> Unit ) { @Composable fun progressIndicator() { @@ -71,6 +70,7 @@ fun CIImageView( when (file.fileProtocol) { FileProtocol.XFTP -> progressIndicator() FileProtocol.SMP -> {} + FileProtocol.LOCAL -> {} } is CIFileStatus.SndTransfer -> progressIndicator() is CIFileStatus.SndComplete -> fileIcon(painterResource(MR.images.ic_check_filled), MR.strings.icon_descr_image_snd_complete) @@ -181,7 +181,7 @@ fun CIImageView( when (file.fileStatus) { CIFileStatus.RcvInvitation -> if (fileSizeValid()) { - receiveFile(file.fileId, encryptLocalFile) + receiveFile(file.fileId) } else { AlertManager.shared.showAlertMsg( generalGetString(MR.strings.large_file), @@ -200,6 +200,7 @@ fun CIImageView( generalGetString(MR.strings.waiting_for_image), generalGetString(MR.strings.image_will_be_received_when_contact_is_online) ) + FileProtocol.LOCAL -> {} } CIFileStatus.RcvTransfer(rcvProgress = 7, rcvTotal = 10) -> {} // ? CIFileStatus.RcvComplete -> {} // ? diff --git a/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/views/chat/item/CIRcvDecryptionError.kt b/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/views/chat/item/CIRcvDecryptionError.kt index 318735d73e..318a8a6a05 100644 --- a/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/views/chat/item/CIRcvDecryptionError.kt +++ b/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/views/chat/item/CIRcvDecryptionError.kt @@ -142,6 +142,7 @@ fun DecryptionErrorItemFixButton( Modifier.clickable(onClick = onClick), shape = RoundedCornerShape(18.dp), color = receivedColor, + contentColor = LocalContentColor.current ) { Box( Modifier.padding(vertical = 6.dp, horizontal = 12.dp), @@ -188,6 +189,7 @@ fun DecryptionErrorItem( Modifier.clickable(onClick = onClick), shape = RoundedCornerShape(18.dp), color = receivedColor, + contentColor = LocalContentColor.current ) { Box( Modifier.padding(vertical = 6.dp, horizontal = 12.dp), diff --git a/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/views/chat/item/CIVIdeoView.kt b/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/views/chat/item/CIVIdeoView.kt index 04ec307358..a5a9521084 100644 --- a/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/views/chat/item/CIVIdeoView.kt +++ b/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/views/chat/item/CIVIdeoView.kt @@ -21,7 +21,6 @@ import chat.simplex.common.views.helpers.* import chat.simplex.common.model.* import chat.simplex.common.platform.* import dev.icerock.moko.resources.StringResource -import kotlinx.coroutines.flow.* import java.io.File import java.net.URI @@ -32,7 +31,7 @@ fun CIVideoView( file: CIFile?, imageProvider: () -> ImageGalleryProvider, showMenu: MutableState<Boolean>, - receiveFile: (Long, Boolean) -> Unit + receiveFile: (Long) -> Unit ) { Box( Modifier.layoutId(CHAT_IMAGE_LAYOUT_ID), @@ -42,7 +41,7 @@ fun CIVideoView( val filePath = remember(file, CIFile.cachedRemoteFileRequests.toList()) { mutableStateOf(getLoadedFilePath(file)) } if (chatModel.connectedToRemote()) { LaunchedEffect(file) { - withBGApi { + withLongRunningApi(slow = 60_000, deadlock = 600_000) { if (file != null && file.loaded && getLoadedFilePath(file) == null) { file.loadRemoteFile(false) filePath.value = getLoadedFilePath(file) @@ -52,21 +51,30 @@ fun CIVideoView( } val f = filePath.value if (file != null && f != null) { - val uri = remember(filePath) { getAppFileUri(f.substringAfterLast(File.separator)) } val view = LocalMultiplatformView() - VideoView(uri, file, preview, duration * 1000L, showMenu, onClick = { + val openFullscreen = { hideKeyboard(view) ModalManager.fullscreen.showCustomModal(animated = false) { close -> ImageFullScreenView(imageProvider, close) } - }) + } + + val uri = remember(filePath) { getAppFileUri(f.substringAfterLast(File.separator)) } + val autoPlay = remember { mutableStateOf(false) } + val uriDecrypted = remember(filePath) { mutableStateOf(if (file.fileSource?.cryptoArgs == null) uri else file.fileSource.decryptedGet()) } + val decrypted = uriDecrypted.value + if (decrypted != null) { + VideoView(decrypted, file, preview, duration * 1000L, autoPlay, showMenu, openFullscreen = openFullscreen) + } else { + VideoViewEncrypted(uriDecrypted, file, preview, duration * 1000L, autoPlay, showMenu, openFullscreen = openFullscreen) + } } else { Box { VideoPreviewImageView(preview, onClick = { if (file != null) { when (file.fileStatus) { CIFileStatus.RcvInvitation -> - receiveFileIfValidSize(file, encrypted = false, receiveFile) + receiveFileIfValidSize(file, receiveFile) CIFileStatus.RcvAccepted -> when (file.fileProtocol) { FileProtocol.XFTP -> @@ -74,12 +82,12 @@ fun CIVideoView( generalGetString(MR.strings.waiting_for_video), generalGetString(MR.strings.video_will_be_received_when_contact_completes_uploading) ) - FileProtocol.SMP -> AlertManager.shared.showAlertMsg( generalGetString(MR.strings.waiting_for_video), generalGetString(MR.strings.video_will_be_received_when_contact_is_online) ) + FileProtocol.LOCAL -> {} } CIFileStatus.RcvTransfer(rcvProgress = 7, rcvTotal = 10) -> {} // ? CIFileStatus.RcvComplete -> {} // ? @@ -95,7 +103,7 @@ fun CIVideoView( DurationProgress(file, remember { mutableStateOf(false) }, remember { mutableStateOf(duration * 1000L) }, remember { mutableStateOf(0L) }/*, soundEnabled*/) } if (file?.fileStatus is CIFileStatus.RcvInvitation) { - PlayButton(error = false, { showMenu.value = true }) { receiveFileIfValidSize(file, encrypted = false, receiveFile) } + PlayButton(error = false, { showMenu.value = true }) { receiveFileIfValidSize(file, receiveFile) } } } } @@ -104,7 +112,40 @@ fun CIVideoView( } @Composable -private fun VideoView(uri: URI, file: CIFile, defaultPreview: ImageBitmap, defaultDuration: Long, showMenu: MutableState<Boolean>, onClick: () -> Unit) { +private fun VideoViewEncrypted( + uriUnencrypted: MutableState<URI?>, + file: CIFile, + defaultPreview: ImageBitmap, + defaultDuration: Long, + autoPlay: MutableState<Boolean>, + showMenu: MutableState<Boolean>, + openFullscreen: () -> Unit, +) { + var decryptionInProgress by rememberSaveable(file.fileName) { mutableStateOf(false) } + val onLongClick = { showMenu.value = true } + Box { + VideoPreviewImageView(defaultPreview, if (decryptionInProgress) {{}} else openFullscreen, onLongClick) + if (decryptionInProgress) { + VideoDecryptionProgress(onLongClick = onLongClick) + } else { + PlayButton(false, onLongClick = onLongClick) { + decryptionInProgress = true + withBGApi { + try { + uriUnencrypted.value = file.fileSource?.decryptedGetOrCreate() + autoPlay.value = uriUnencrypted.value != null + } finally { + decryptionInProgress = false + } + } + } + } + DurationProgress(file, remember { mutableStateOf(false) }, remember { mutableStateOf(defaultDuration) }, remember { mutableStateOf(0L) }) + } +} + +@Composable +private fun VideoView(uri: URI, file: CIFile, defaultPreview: ImageBitmap, defaultDuration: Long, autoPlay: MutableState<Boolean>, showMenu: MutableState<Boolean>, openFullscreen: () -> Unit) { val player = remember(uri) { VideoPlayerHolder.getOrCreate(uri, false, defaultPreview, defaultDuration, true) } val videoPlaying = remember(uri.path) { player.videoPlaying } val progress = remember(uri.path) { player.progress } @@ -121,6 +162,13 @@ private fun VideoView(uri: URI, file: CIFile, defaultPreview: ImageBitmap, defau player.stop() } val showPreview = remember { derivedStateOf { !videoPlaying.value || progress.value == 0L } } + LaunchedEffect(uri) { + if (autoPlay.value) play() + } + // Drop autoPlay only when show preview changes to prevent blinking of the view + KeyChangeEffect(showPreview.value) { + autoPlay.value = false + } DisposableEffect(Unit) { onDispose { stop() @@ -133,13 +181,15 @@ private fun VideoView(uri: URI, file: CIFile, defaultPreview: ImageBitmap, defau PlayerView( player, width, - onClick = onClick, + onClick = openFullscreen, onLongClick = onLongClick, stop ) if (showPreview.value) { - VideoPreviewImageView(preview, onClick, onLongClick) - PlayButton(brokenVideo, onLongClick = onLongClick, play) + VideoPreviewImageView(preview, openFullscreen, onLongClick) + if (!autoPlay.value) { + PlayButton(brokenVideo, onLongClick = onLongClick, play) + } } DurationProgress(file, videoPlaying, duration, progress/*, soundEnabled*/) } @@ -153,7 +203,8 @@ private fun BoxScope.PlayButton(error: Boolean = false, onLongClick: () -> Unit, Surface( Modifier.align(Alignment.Center), color = Color.Black.copy(alpha = 0.25f), - shape = RoundedCornerShape(percent = 50) + shape = RoundedCornerShape(percent = 50), + contentColor = LocalContentColor.current ) { Box( Modifier @@ -171,6 +222,31 @@ private fun BoxScope.PlayButton(error: Boolean = false, onLongClick: () -> Unit, } } +@Composable +fun BoxScope.VideoDecryptionProgress(onLongClick: () -> Unit) { + Surface( + Modifier.align(Alignment.Center), + color = Color.Black.copy(alpha = 0.25f), + shape = RoundedCornerShape(percent = 50), + contentColor = LocalContentColor.current + ) { + Box( + Modifier + .defaultMinSize(minWidth = 40.dp, minHeight = 40.dp) + .combinedClickable(onClick = {}, onLongClick = onLongClick) + .onRightClick { onLongClick.invoke() }, + contentAlignment = Alignment.Center + ) { + CircularProgressIndicator( + Modifier + .size(30.dp), + color = Color.White, + strokeWidth = 2.5.dp + ) + } + } +} + @Composable private fun DurationProgress(file: CIFile, playing: MutableState<Boolean>, duration: MutableState<Long>, progress: MutableState<Long>/*, soundEnabled: MutableState<Boolean>*/) { if (duration.value > 0L || progress.value > 0) { @@ -234,6 +310,22 @@ fun VideoPreviewImageView(preview: ImageBitmap, onClick: () -> Unit, onLongClick ) } +@Composable +fun VideoPreviewImageViewFullScreen(preview: ImageBitmap, onClick: () -> Unit, onLongClick: () -> Unit) { + Image( + preview, + contentDescription = stringResource(MR.strings.video_descr), + modifier = Modifier + .fillMaxSize() + .combinedClickable( + onLongClick = onLongClick, + onClick = onClick + ) + .onRightClick(onLongClick), + contentScale = ContentScale.FillWidth, + ) +} + @Composable expect fun LocalWindowWidth(): Dp @@ -264,7 +356,8 @@ private fun progressCircle(progress: Long, total: Long) { Surface( Modifier.drawRingModifier(angle, strokeColor, strokeWidth), color = Color.Transparent, - shape = MaterialTheme.shapes.small.copy(CornerSize(percent = 50)) + shape = MaterialTheme.shapes.small.copy(CornerSize(percent = 50)), + contentColor = LocalContentColor.current ) { Box(Modifier.size(16.dp)) } @@ -284,11 +377,13 @@ private fun loadingIndicator(file: CIFile?) { when (file.fileProtocol) { FileProtocol.XFTP -> progressIndicator() FileProtocol.SMP -> {} + FileProtocol.LOCAL -> {} } is CIFileStatus.SndTransfer -> when (file.fileProtocol) { FileProtocol.XFTP -> progressCircle(file.fileStatus.sndProgress, file.fileStatus.sndTotal) FileProtocol.SMP -> progressIndicator() + FileProtocol.LOCAL -> {} } is CIFileStatus.SndComplete -> fileIcon(painterResource(MR.images.ic_check_filled), MR.strings.icon_descr_video_snd_complete) is CIFileStatus.SndCancelled -> fileIcon(painterResource(MR.images.ic_close), MR.strings.icon_descr_file) @@ -317,9 +412,9 @@ private fun fileSizeValid(file: CIFile?): Boolean { return false } -private fun receiveFileIfValidSize(file: CIFile, encrypted: Boolean, receiveFile: (Long, Boolean) -> Unit) { +private fun receiveFileIfValidSize(file: CIFile, receiveFile: (Long) -> Unit) { if (fileSizeValid(file)) { - receiveFile(file.fileId, encrypted) + receiveFile(file.fileId) } else { AlertManager.shared.showAlertMsg( generalGetString(MR.strings.large_file), diff --git a/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/views/chat/item/CIVoiceView.kt b/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/views/chat/item/CIVoiceView.kt index 0c8487458f..e59c5f1370 100644 --- a/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/views/chat/item/CIVoiceView.kt +++ b/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/views/chat/item/CIVoiceView.kt @@ -36,7 +36,7 @@ fun CIVoiceView( ci: ChatItem, timedMessagesTTL: Int?, longClick: () -> Unit, - receiveFile: (Long, Boolean) -> Unit, + receiveFile: (Long) -> Unit, ) { Row( Modifier.padding(top = if (hasText) 14.dp else 4.dp, bottom = if (hasText) 14.dp else 6.dp, start = if (hasText) 6.dp else 0.dp, end = if (hasText) 6.dp else 0.dp), @@ -105,7 +105,7 @@ private fun VoiceLayout( play: () -> Unit, pause: () -> Unit, longClick: () -> Unit, - receiveFile: (Long, Boolean) -> Unit, + receiveFile: (Long) -> Unit, onProgressChanged: (Int) -> Unit, ) { @Composable @@ -225,7 +225,8 @@ private fun PlayPauseButton( Surface( Modifier.drawRingModifier(angle, strokeColor, strokeWidth), color = if (sent) sentColor else receivedColor, - shape = MaterialTheme.shapes.small.copy(CornerSize(percent = 50)) + shape = MaterialTheme.shapes.small.copy(CornerSize(percent = 50)), + contentColor = LocalContentColor.current ) { Box( Modifier @@ -259,7 +260,7 @@ private fun VoiceMsgIndicator( play: () -> Unit, pause: () -> Unit, longClick: () -> Unit, - receiveFile: (Long, Boolean) -> Unit, + receiveFile: (Long) -> Unit, ) { val strokeWidth = with(LocalDensity.current) { 3.dp.toPx() } val strokeColor = MaterialTheme.colors.primary @@ -279,7 +280,7 @@ private fun VoiceMsgIndicator( } } else { if (file?.fileStatus is CIFileStatus.RcvInvitation) { - PlayPauseButton(audioPlaying, sent, 0f, strokeWidth, strokeColor, true, error, { receiveFile(file.fileId, chatController.appPrefs.privacyEncryptLocalFiles.get()) }, {}, longClick = longClick) + PlayPauseButton(audioPlaying, sent, 0f, strokeWidth, strokeColor, true, error, { receiveFile(file.fileId) }, {}, longClick = longClick) } else if (file?.fileStatus is CIFileStatus.RcvTransfer || file?.fileStatus is CIFileStatus.RcvAccepted ) { diff --git a/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/views/chat/item/ChatItemView.kt b/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/views/chat/item/ChatItemView.kt index daf887e8c3..549f5f2f52 100644 --- a/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/views/chat/item/ChatItemView.kt +++ b/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/views/chat/item/ChatItemView.kt @@ -50,7 +50,7 @@ fun ChatItemView( range: IntRange?, deleteMessage: (Long, CIDeleteMode) -> Unit, deleteMessages: (List<Long>) -> Unit, - receiveFile: (Long, Boolean) -> Unit, + receiveFile: (Long) -> Unit, cancelFile: (Long) -> Unit, joinGroup: (Long, () -> Unit) -> Unit, acceptCall: (Contact) -> Unit, @@ -183,7 +183,7 @@ fun ChatItemView( if (cInfo.featureEnabled(ChatFeature.Reactions) && cItem.allowAddReaction) { MsgReactionsMenu() } - if (cItem.meta.itemDeleted == null && !live) { + if (cItem.meta.itemDeleted == null && !live && !cItem.localNote) { ItemAction(stringResource(MR.strings.reply_verb), painterResource(MR.images.ic_reply), onClick = { if (composeState.value.editing) { composeState.value = ComposeState(contextItem = ComposeContextItem.QuotedItem(cItem), useLinkPreviews = useLinkPreviews) @@ -213,7 +213,7 @@ fun ChatItemView( showMenu.value = false } if (chatModel.connectedToRemote() && fileSource == null) { - withBGApi { + withLongRunningApi(slow = 60_000, deadlock = 600_000) { cItem.file?.loadRemoteFile(true) fileSource = getLoadedFileSource(cItem.file) shareIfExists() @@ -240,7 +240,7 @@ fun ChatItemView( if (revealed.value) { HideItemAction(revealed, showMenu) } - if (cItem.meta.itemDeleted == null && cItem.file != null && cItem.file.cancelAction != null) { + if (cItem.meta.itemDeleted == null && cItem.file != null && cItem.file.cancelAction != null && !cItem.localNote) { CancelFileItemAction(cItem.file.fileId, showMenu, cancelFile = cancelFile, cancelAction = cItem.file.cancelAction) } if (!(live && cItem.meta.isLive)) { @@ -319,7 +319,7 @@ fun ChatItemView( } } - @Composable fun DeletedItem() { + @Composable fun LegacyDeletedItem() { DeletedItemView(cItem, cInfo.timedMessagesTTL) DefaultDropdownMenu(showMenu) { ItemInfoAction(cInfo, cItem, showItemDetails, showMenu) @@ -371,7 +371,7 @@ fun ChatItemView( } @Composable - fun ModeratedItem() { + fun DeletedItem() { MarkedDeletedItemView(cItem, cInfo.timedMessagesTTL, revealed) DefaultDropdownMenu(showMenu) { ItemInfoAction(cInfo, cItem, showItemDetails, showMenu) @@ -382,8 +382,8 @@ fun ChatItemView( when (val c = cItem.content) { is CIContent.SndMsgContent -> ContentItem() is CIContent.RcvMsgContent -> ContentItem() - is CIContent.SndDeleted -> DeletedItem() - is CIContent.RcvDeleted -> DeletedItem() + is CIContent.SndDeleted -> LegacyDeletedItem() + is CIContent.RcvDeleted -> LegacyDeletedItem() is CIContent.SndCall -> CallItem(c.status, c.duration) is CIContent.RcvCall -> CallItem(c.status, c.duration) is CIContent.RcvIntegrityError -> if (developerTools) { @@ -449,8 +449,9 @@ fun ChatItemView( CIChatFeatureView(cItem, c.groupFeature, Color.Red, revealed = revealed, showMenu = showMenu) MsgContentItemDropdownMenu() } - is CIContent.SndModerated -> ModeratedItem() - is CIContent.RcvModerated -> ModeratedItem() + is CIContent.SndModerated -> DeletedItem() + is CIContent.RcvModerated -> DeletedItem() + is CIContent.RcvBlocked -> DeletedItem() is CIContent.InvalidJSON -> CIInvalidJSONView(c.json) } } @@ -613,7 +614,7 @@ private fun ShrinkItemAction(revealed: MutableState<Boolean>, showMenu: MutableS @Composable fun ItemAction(text: String, icon: Painter, color: Color = Color.Unspecified, onClick: () -> Unit) { val finalColor = if (color == Color.Unspecified) { - if (isInDarkTheme()) MenuTextColorDark else Color.Black + MenuTextColor } else color DropdownMenuItem(onClick, contentPadding = PaddingValues(horizontal = DEFAULT_PADDING * 1.5f)) { Row(verticalAlignment = Alignment.CenterVertically) { @@ -633,7 +634,7 @@ fun ItemAction(text: String, icon: Painter, color: Color = Color.Unspecified, on @Composable fun ItemAction(text: String, icon: ImageVector, onClick: () -> Unit, color: Color = Color.Unspecified) { val finalColor = if (color == Color.Unspecified) { - if (isInDarkTheme()) MenuTextColorDark else Color.Black + MenuTextColor } else color DropdownMenuItem(onClick, contentPadding = PaddingValues(horizontal = DEFAULT_PADDING * 1.5f)) { Row(verticalAlignment = Alignment.CenterVertically) { @@ -677,7 +678,7 @@ fun deleteMessageAlertDialog(chatItem: ChatItem, questionText: String, deleteMes deleteMessage(chatItem.id, CIDeleteMode.cidmInternal) AlertManager.shared.hideAlert() }) { Text(stringResource(MR.strings.for_me_only), color = MaterialTheme.colors.error) } - if (chatItem.meta.editable) { + if (chatItem.meta.editable && !chatItem.localNote) { Spacer(Modifier.padding(horizontal = 4.dp)) TextButton(onClick = { deleteMessage(chatItem.id, CIDeleteMode.cidmBroadcast) @@ -746,7 +747,7 @@ fun PreviewChatItemView() { range = 0..1, deleteMessage = { _, _ -> }, deleteMessages = { _ -> }, - receiveFile = { _, _ -> }, + receiveFile = { _ -> }, cancelFile = {}, joinGroup = { _, _ -> }, acceptCall = { _ -> }, @@ -780,7 +781,7 @@ fun PreviewChatItemViewDeletedContent() { range = 0..1, deleteMessage = { _, _ -> }, deleteMessages = { _ -> }, - receiveFile = { _, _ -> }, + receiveFile = { _ -> }, cancelFile = {}, joinGroup = { _, _ -> }, acceptCall = { _ -> }, diff --git a/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/views/chat/item/DeletedItemView.kt b/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/views/chat/item/DeletedItemView.kt index 2d949e1737..7514b6e280 100644 --- a/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/views/chat/item/DeletedItemView.kt +++ b/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/views/chat/item/DeletedItemView.kt @@ -23,6 +23,7 @@ fun DeletedItemView(ci: ChatItem, timedMessagesTTL: Int?) { Surface( shape = RoundedCornerShape(18.dp), color = if (sent) sentColor else receivedColor, + contentColor = LocalContentColor.current ) { Row( Modifier.padding(horizontal = 12.dp, vertical = 6.dp), diff --git a/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/views/chat/item/FramedItemView.kt b/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/views/chat/item/FramedItemView.kt index c391200c2d..641e6affab 100644 --- a/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/views/chat/item/FramedItemView.kt +++ b/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/views/chat/item/FramedItemView.kt @@ -35,7 +35,7 @@ fun FramedItemView( imageProvider: (() -> ImageGalleryProvider)? = null, linkMode: SimplexLinkMode, showMenu: MutableState<Boolean>, - receiveFile: (Long, Boolean) -> Unit, + receiveFile: (Long) -> Unit, onLinkLongClick: (link: String) -> Unit = {}, scrollToItem: (Long) -> Unit = {}, ) { @@ -54,6 +54,7 @@ fun FramedItemView( MarkdownText( qi.text, qi.formattedText, + toggleSecrets = true, maxLines = lines, overflow = TextOverflow.Ellipsis, style = TextStyle(fontSize = 15.sp, color = MaterialTheme.colors.onSurface), @@ -208,7 +209,10 @@ fun FramedItemView( is CIDeleted.Blocked -> { FramedItemHeader(stringResource(MR.strings.blocked_item_description), true, painterResource(MR.images.ic_back_hand)) } - else -> { + is CIDeleted.BlockedByAdmin -> { + FramedItemHeader(stringResource(MR.strings.blocked_by_admin_item_description), true, painterResource(MR.images.ic_back_hand)) + } + is CIDeleted.Deleted -> { FramedItemHeader(stringResource(MR.strings.marked_deleted_description), true, painterResource(MR.images.ic_delete)) } } @@ -231,7 +235,7 @@ fun FramedItemView( } else { when (val mc = ci.content.msgContent) { is MsgContent.MCImage -> { - CIImageView(image = mc.image, file = ci.file, ci.encryptLocalFile, metaColor = metaColor, imageProvider ?: return@PriorityLayout, showMenu, receiveFile) + CIImageView(image = mc.image, file = ci.file, metaColor = metaColor, imageProvider ?: return@PriorityLayout, showMenu, receiveFile) if (mc.text == "" && !ci.meta.isLive) { metaColor = Color.White } else { @@ -288,7 +292,7 @@ fun CIMarkdownText( Box(Modifier.padding(vertical = 6.dp, horizontal = 12.dp)) { val text = if (ci.meta.isLive) ci.content.msgContent?.text ?: ci.text else ci.text MarkdownText( - text, if (text.isEmpty()) emptyList() else ci.formattedText, + text, if (text.isEmpty()) emptyList() else ci.formattedText, toggleSecrets = true, meta = ci.meta, chatTTL = chatTTL, linkMode = linkMode, uriHandler = uriHandler, senderBold = true, onLinkLongClick = onLinkLongClick ) diff --git a/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/views/chat/item/ImageFullScreenView.kt b/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/views/chat/item/ImageFullScreenView.kt index c7268592bf..16d59f6aeb 100644 --- a/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/views/chat/item/ImageFullScreenView.kt +++ b/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/views/chat/item/ImageFullScreenView.kt @@ -12,6 +12,7 @@ import androidx.compose.ui.Modifier import androidx.compose.ui.graphics.* import androidx.compose.ui.input.pointer.* import androidx.compose.ui.layout.onGloballyPositioned +import chat.simplex.common.model.CryptoFile import chat.simplex.common.platform.* import chat.simplex.common.views.chat.ProviderMedia import chat.simplex.common.views.helpers.* @@ -86,6 +87,8 @@ fun ImageFullScreenView(imageProvider: () -> ImageGalleryProvider, close: () -> provider.scrollToStart() pagerState.scrollToPage(0) } + // Current media was deleted or moderated, close gallery + index -> close() } } } @@ -134,9 +137,15 @@ fun ImageFullScreenView(imageProvider: () -> ImageGalleryProvider, close: () -> FullScreenImageView(modifier, data, imageBitmap) } else if (media is ProviderMedia.Video) { val preview = remember(media.uri.path) { base64ToBitmap(media.preview) } - VideoView(modifier, media.uri, preview, index == settledCurrentPage, close) - DisposableEffect(Unit) { - onDispose { playersToRelease.add(media.uri) } + val uriDecrypted = remember(media.uri.path) { mutableStateOf(if (media.fileSource?.cryptoArgs == null) media.uri else media.fileSource.decryptedGet()) } + val decrypted = uriDecrypted.value + if (decrypted != null) { + VideoView(modifier, decrypted, preview, index == settledCurrentPage, close) + DisposableEffect(Unit) { + onDispose { playersToRelease.add(decrypted) } + } + } else if (media.fileSource != null) { + VideoViewEncrypted(uriDecrypted, media.fileSource, preview) } } } @@ -152,6 +161,19 @@ fun ImageFullScreenView(imageProvider: () -> ImageGalleryProvider, close: () -> @Composable expect fun FullScreenImageView(modifier: Modifier, data: ByteArray, imageBitmap: ImageBitmap) +@Composable +private fun VideoViewEncrypted(uriUnencrypted: MutableState<URI?>, fileSource: CryptoFile, defaultPreview: ImageBitmap) { + LaunchedEffect(Unit) { + withBGApi { + uriUnencrypted.value = fileSource.decryptedGetOrCreate() + } + } + Box(contentAlignment = Alignment.Center) { + VideoPreviewImageViewFullScreen(defaultPreview, {}, {}) + VideoDecryptionProgress {} + } +} + @Composable private fun VideoView(modifier: Modifier, uri: URI, defaultPreview: ImageBitmap, currentPage: Boolean, close: () -> Unit) { val player = remember(uri) { VideoPlayerHolder.getOrCreate(uri, true, defaultPreview, 0L, true) } diff --git a/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/views/chat/item/IntegrityErrorItemView.kt b/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/views/chat/item/IntegrityErrorItemView.kt index 582730b8f5..7be0cc2f6c 100644 --- a/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/views/chat/item/IntegrityErrorItemView.kt +++ b/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/views/chat/item/IntegrityErrorItemView.kt @@ -56,6 +56,7 @@ fun CIMsgError(ci: ChatItem, timedMessagesTTL: Int?, onClick: () -> Unit) { Modifier.clickable(onClick = onClick), shape = RoundedCornerShape(18.dp), color = receivedColor, + contentColor = LocalContentColor.current ) { Row( Modifier.padding(horizontal = 12.dp, vertical = 6.dp), diff --git a/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/views/chat/item/MarkedDeletedItemView.kt b/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/views/chat/item/MarkedDeletedItemView.kt index 50d905ef76..f7783d682a 100644 --- a/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/views/chat/item/MarkedDeletedItemView.kt +++ b/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/views/chat/item/MarkedDeletedItemView.kt @@ -26,6 +26,7 @@ fun MarkedDeletedItemView(ci: ChatItem, timedMessagesTTL: Int?, revealed: Mutabl Surface( shape = RoundedCornerShape(18.dp), color = if (ci.chatDir.sent) sentColor else receivedColor, + contentColor = LocalContentColor.current ) { Row( Modifier.padding(horizontal = 12.dp, vertical = 6.dp), @@ -47,6 +48,7 @@ private fun MergedMarkedDeletedText(chatItem: ChatItem, revealed: MutableState<B val reversedChatItems = ChatModel.chatItems.asReversed() var moderated = 0 var blocked = 0 + var blockedByAdmin = 0 var deleted = 0 val moderatedBy: MutableSet<String> = mutableSetOf() while (i < reversedChatItems.size) { @@ -58,16 +60,19 @@ private fun MergedMarkedDeletedText(chatItem: ChatItem, revealed: MutableState<B moderatedBy.add(itemDeleted.byGroupMember.displayName) } is CIDeleted.Blocked -> blocked += 1 + is CIDeleted.BlockedByAdmin -> blockedByAdmin +=1 is CIDeleted.Deleted -> deleted += 1 } i++ } - val total = moderated + blocked + deleted + val total = moderated + blocked + blockedByAdmin + deleted if (total <= 1) markedDeletedText(chatItem.meta) else if (total == moderated) stringResource(MR.strings.moderated_items_description).format(total, moderatedBy.joinToString(", ")) - else if (total == blocked) + else if (total == blockedByAdmin) + stringResource(MR.strings.blocked_by_admin_items_description).format(total) + else if (total == blocked + blockedByAdmin) stringResource(MR.strings.blocked_items_description).format(total) else stringResource(MR.strings.marked_deleted_items_description).format(total) @@ -92,7 +97,9 @@ private fun markedDeletedText(meta: CIMeta): String = String.format(generalGetString(MR.strings.moderated_item_description), meta.itemDeleted.byGroupMember.displayName) is CIDeleted.Blocked -> generalGetString(MR.strings.blocked_item_description) - else -> + is CIDeleted.BlockedByAdmin -> + generalGetString(MR.strings.blocked_by_admin_item_description) + is CIDeleted.Deleted, null -> generalGetString(MR.strings.marked_deleted_description) } diff --git a/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/views/chat/item/TextItemView.kt b/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/views/chat/item/TextItemView.kt index ff1267d0fa..5169d944c8 100644 --- a/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/views/chat/item/TextItemView.kt +++ b/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/views/chat/item/TextItemView.kt @@ -60,6 +60,7 @@ fun MarkdownText ( sender: String? = null, meta: CIMeta? = null, chatTTL: Int? = null, + toggleSecrets: Boolean, style: TextStyle = MaterialTheme.typography.body1.copy(color = MaterialTheme.colors.onSurface, lineHeight = 22.sp), maxLines: Int = Int.MAX_VALUE, overflow: TextOverflow = TextOverflow.Clip, @@ -89,6 +90,7 @@ fun MarkdownText ( ) { var timer: Job? by remember { mutableStateOf(null) } var typingIdx by rememberSaveable { mutableStateOf(0) } + val showSecrets = remember { mutableStateMapOf<String, Boolean>() } fun stopTyping() { timer?.cancel() timer = null @@ -127,15 +129,22 @@ fun MarkdownText ( } Text(annotatedText, style = style, modifier = modifier, maxLines = maxLines, overflow = overflow, inlineContent = inlineContent ?: mapOf()) } else { - var hasLinks = false + var hasAnnotations = false val annotatedText = buildAnnotatedString { appendSender(this, sender, senderBold) - for (ft in formattedText) { + for ((i, ft) in formattedText.withIndex()) { if (ft.format == null) append(ft.text) - else { + else if (toggleSecrets && ft.format is Format.Secret) { + val ftStyle = ft.format.style + hasAnnotations = true + val key = i.toString() + withAnnotation(tag = "SECRET", annotation = key) { + if (showSecrets[key] == true) append(ft.text) else withStyle(ftStyle) { append(ft.text) } + } + } else { val link = ft.link(linkMode) if (link != null) { - hasLinks = true + hasAnnotations = true val ftStyle = ft.format.style withAnnotation(tag = if (ft.format is Format.SimplexLink) "SIMPLEX_URL" else "URL", annotation = link) { withStyle(ftStyle) { append(ft.viewText(linkMode)) } @@ -153,7 +162,7 @@ fun MarkdownText ( withStyle(reserveTimestampStyle) { append("\n" + metaText) } else */if (meta != null) withStyle(reserveTimestampStyle) { append(reserve) } } - if (hasLinks && uriHandler != null) { + if (hasAnnotations && uriHandler != null) { val icon = remember { mutableStateOf(PointerIcon.Default) } ClickableText(annotatedText, style = style, modifier = modifier.pointerHoverIcon(icon.value), maxLines = maxLines, overflow = overflow, onLongClick = { offset -> @@ -177,12 +186,20 @@ fun MarkdownText ( .firstOrNull()?.let { annotation -> uriHandler.openVerifiedSimplexUri(annotation.item) } + annotatedText.getStringAnnotations(tag = "SECRET", start = offset, end = offset) + .firstOrNull()?.let { annotation -> + val key = annotation.item + showSecrets[key] = !(showSecrets[key] ?: false) + } }, onHover = { offset -> icon.value = annotatedText.getStringAnnotations(tag = "URL", start = offset, end = offset) .firstOrNull()?.let { PointerIcon.Hand } ?: annotatedText.getStringAnnotations(tag = "SIMPLEX_URL", start = offset, end = offset) + .firstOrNull()?.let { + PointerIcon.Hand + } ?: annotatedText.getStringAnnotations(tag = "SECRET", start = offset, end = offset) .firstOrNull()?.let { PointerIcon.Hand } ?: PointerIcon.Default diff --git a/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/views/chatlist/ChatHelpView.kt b/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/views/chatlist/ChatHelpView.kt index 866ad04b02..f36978cd3c 100644 --- a/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/views/chatlist/ChatHelpView.kt +++ b/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/views/chatlist/ChatHelpView.kt @@ -50,8 +50,8 @@ fun ChatHelpView(addContact: (() -> Unit)? = null) { ) Text(stringResource(MR.strings.above_then_preposition_continuation)) } - Text(annotatedStringResource(MR.strings.add_new_contact_to_create_one_time_QR_code), lineHeight = 22.sp) - Text(annotatedStringResource(MR.strings.scan_QR_code_to_connect_to_contact_who_shows_QR_code), lineHeight = 22.sp) + Text(annotatedStringResource(MR.strings.add_contact_button_to_create_link_or_connect_via_link), lineHeight = 22.sp) + Text(annotatedStringResource(MR.strings.create_group_button_to_create_new_group), lineHeight = 22.sp) } Column( diff --git a/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/views/chatlist/ChatListNavLinkView.kt b/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/views/chatlist/ChatListNavLinkView.kt index 8d5446aa53..15b1db6c44 100644 --- a/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/views/chatlist/ChatListNavLinkView.kt +++ b/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/views/chatlist/ChatListNavLinkView.kt @@ -24,28 +24,26 @@ import chat.simplex.common.ui.theme.* import chat.simplex.common.views.chat.* import chat.simplex.common.views.chat.group.deleteGroupDialog import chat.simplex.common.views.chat.group.leaveGroupDialog -import chat.simplex.common.views.chat.item.InvalidJSONView import chat.simplex.common.views.chat.item.ItemAction import chat.simplex.common.views.helpers.* import chat.simplex.common.views.newchat.* import chat.simplex.res.MR import kotlinx.coroutines.delay import kotlinx.datetime.Clock -import java.net.URI @Composable -fun ChatListNavLinkView(chat: Chat, chatModel: ChatModel) { +fun ChatListNavLinkView(chat: Chat, nextChatSelected: State<Boolean>) { val showMenu = remember { mutableStateOf(false) } val showMarkRead = remember(chat.chatStats.unreadCount, chat.chatStats.unreadChat) { chat.chatStats.unreadCount > 0 || chat.chatStats.unreadChat } - val stopped = chatModel.chatRunning.value == false + val disabled = chatModel.chatRunning.value == false || chatModel.deletedChats.value.contains(chat.remoteHostId to chat.chatInfo.id) val linkMode by remember { chatModel.controller.appPrefs.simplexLinkMode.state } LaunchedEffect(chat.id) { showMenu.value = false delay(500L) } - val selectedChat = remember(chat.id) { derivedStateOf { chat.id == ChatModel.chatId.value } } + val selectedChat = remember(chat.id) { derivedStateOf { chat.id == chatModel.chatId.value } } val showChatPreviews = chatModel.showChatPreviews.value val inProgress = remember { mutableStateOf(false) } var progressByTimeout by rememberSaveable { mutableStateOf(false) } @@ -64,7 +62,7 @@ fun ChatListNavLinkView(chat: Chat, chatModel: ChatModel) { ChatListNavLinkLayout( chatLinkPreview = { tryOrShowError("${chat.id}ChatListNavLink", error = { ErrorChatListItem() }) { - ChatPreviewView(chat, showChatPreviews, chatModel.draft.value, chatModel.draftChatId.value, chatModel.currentUser.value?.profile?.displayName, contactNetworkStatus, stopped, linkMode, inProgress = false, progressByTimeout = false) + ChatPreviewView(chat, showChatPreviews, chatModel.draft.value, chatModel.draftChatId.value, chatModel.currentUser.value?.profile?.displayName, contactNetworkStatus, disabled, linkMode, inProgress = false, progressByTimeout = false) } }, click = { directChatAction(chat.remoteHostId, chat.chatInfo.contact, chatModel) }, @@ -74,15 +72,16 @@ fun ChatListNavLinkView(chat: Chat, chatModel: ChatModel) { } }, showMenu, - stopped, - selectedChat + disabled, + selectedChat, + nextChatSelected, ) } is ChatInfo.Group -> ChatListNavLinkLayout( chatLinkPreview = { tryOrShowError("${chat.id}ChatListNavLink", error = { ErrorChatListItem() }) { - ChatPreviewView(chat, showChatPreviews, chatModel.draft.value, chatModel.draftChatId.value, chatModel.currentUser.value?.profile?.displayName, null, stopped, linkMode, inProgress.value, progressByTimeout) + ChatPreviewView(chat, showChatPreviews, chatModel.draft.value, chatModel.draftChatId.value, chatModel.currentUser.value?.profile?.displayName, null, disabled, linkMode, inProgress.value, progressByTimeout) } }, click = { if (!inProgress.value) groupChatAction(chat.remoteHostId, chat.chatInfo.groupInfo, chatModel, inProgress) }, @@ -92,9 +91,29 @@ fun ChatListNavLinkView(chat: Chat, chatModel: ChatModel) { } }, showMenu, - stopped, - selectedChat + disabled, + selectedChat, + nextChatSelected, ) + is ChatInfo.Local -> { + ChatListNavLinkLayout( + chatLinkPreview = { + tryOrShowError("${chat.id}ChatListNavLink", error = { ErrorChatListItem() }) { + ChatPreviewView(chat, showChatPreviews, chatModel.draft.value, chatModel.draftChatId.value, chatModel.currentUser.value?.profile?.displayName, null, disabled, linkMode, inProgress = false, progressByTimeout = false) + } + }, + click = { noteFolderChatAction(chat.remoteHostId, chat.chatInfo.noteFolder) }, + dropdownMenuItems = { + tryOrShowError("${chat.id}ChatListNavLinkDropdown", error = {}) { + NoteFolderMenuItems(chat, showMenu, showMarkRead) + } + }, + showMenu, + disabled, + selectedChat, + nextChatSelected, + ) + } is ChatInfo.ContactRequest -> ChatListNavLinkLayout( chatLinkPreview = { @@ -109,8 +128,9 @@ fun ChatListNavLinkView(chat: Chat, chatModel: ChatModel) { } }, showMenu, - stopped, - selectedChat + disabled, + selectedChat, + nextChatSelected, ) is ChatInfo.ContactConnection -> ChatListNavLinkLayout( @@ -120,11 +140,7 @@ fun ChatListNavLinkView(chat: Chat, chatModel: ChatModel) { } }, click = { - ModalManager.center.closeModals() - ModalManager.end.closeModals() - ModalManager.center.showModalCloseable(true, showClose = appPlatform.isAndroid) { close -> - ContactConnectionInfoView(chatModel, chat.remoteHostId, chat.chatInfo.contactConnection.connReqInv, chat.chatInfo.contactConnection, false, close) - } + chatModel.chatId.value = chat.id }, dropdownMenuItems = { tryOrShowError("${chat.id}ChatListNavLinkDropdown", error = {}) { @@ -132,8 +148,9 @@ fun ChatListNavLinkView(chat: Chat, chatModel: ChatModel) { } }, showMenu, - stopped, - selectedChat + disabled, + selectedChat, + nextChatSelected, ) is ChatInfo.InvalidJSON -> ChatListNavLinkLayout( @@ -143,13 +160,13 @@ fun ChatListNavLinkView(chat: Chat, chatModel: ChatModel) { } }, click = { - ModalManager.end.closeModals() - ModalManager.center.showModal(true) { InvalidJSONView(chat.chatInfo.json) } + chatModel.chatId.value = chat.id }, dropdownMenuItems = null, showMenu, - stopped, - selectedChat + disabled, + selectedChat, + nextChatSelected, ) } } @@ -176,6 +193,10 @@ fun groupChatAction(rhId: Long?, groupInfo: GroupInfo, chatModel: ChatModel, inP } } +fun noteFolderChatAction(rhId: Long?, noteFolder: NoteFolder) { + withBGApi { openChat(rhId, ChatInfo.Local(noteFolder), chatModel) } +} + suspend fun openDirectChat(rhId: Long?, contactId: Long, chatModel: ChatModel) { val chat = chatModel.controller.apiGetChat(rhId, ChatType.Direct, contactId) if (chat != null) { @@ -249,7 +270,7 @@ fun ContactMenuItems(chat: Chat, contact: Contact, chatModel: ChatModel, showMen } ToggleFavoritesChatAction(chat, chatModel, chat.chatInfo.chatSettings?.favorite == true, showMenu) ToggleNotificationsChatAction(chat, chatModel, chat.chatInfo.ntfsEnabled, showMenu) - ClearChatAction(chat, chatModel, showMenu) + ClearChatAction(chat, showMenu) } DeleteContactAction(chat, chatModel, showMenu) } @@ -288,7 +309,7 @@ fun GroupMenuItems( } ToggleFavoritesChatAction(chat, chatModel, chat.chatInfo.chatSettings?.favorite == true, showMenu) ToggleNotificationsChatAction(chat, chatModel, chat.chatInfo.ntfsEnabled, showMenu) - ClearChatAction(chat, chatModel, showMenu) + ClearChatAction(chat, showMenu) if (groupInfo.membership.memberCurrent) { LeaveGroupAction(chat.remoteHostId, groupInfo, chatModel, showMenu) } @@ -299,6 +320,16 @@ fun GroupMenuItems( } } +@Composable +fun NoteFolderMenuItems(chat: Chat, showMenu: MutableState<Boolean>, showMarkRead: Boolean) { + if (showMarkRead) { + MarkReadChatAction(chat, chatModel, showMenu) + } else { + MarkUnreadChatAction(chat, chatModel, showMenu) + } + ClearNoteFolderAction(chat, showMenu) +} + @Composable fun MarkReadChatAction(chat: Chat, chatModel: ChatModel, showMenu: MutableState<Boolean>) { ItemAction( @@ -349,12 +380,25 @@ fun ToggleNotificationsChatAction(chat: Chat, chatModel: ChatModel, ntfsEnabled: } @Composable -fun ClearChatAction(chat: Chat, chatModel: ChatModel, showMenu: MutableState<Boolean>) { +fun ClearChatAction(chat: Chat, showMenu: MutableState<Boolean>) { ItemAction( stringResource(MR.strings.clear_chat_menu_action), painterResource(MR.images.ic_settings_backup_restore), onClick = { - clearChatDialog(chat, chatModel) + clearChatDialog(chat) + showMenu.value = false + }, + color = WarningOrange + ) +} + +@Composable +fun ClearNoteFolderAction(chat: Chat, showMenu: MutableState<Boolean>) { + ItemAction( + stringResource(MR.strings.clear_chat_menu_action), + painterResource(MR.images.ic_settings_backup_restore), + onClick = { + clearNoteFolderDialog(chat) showMenu.value = false }, color = WarningOrange @@ -396,7 +440,7 @@ fun JoinGroupAction( inProgress: MutableState<Boolean> ) { val joinGroup: () -> Unit = { - withApi { + withBGApi { inProgress.value = true chatModel.controller.apiJoinGroup(chat.remoteHostId, groupInfo.groupId) inProgress.value = false @@ -476,10 +520,7 @@ fun ContactConnectionMenuItems(rhId: Long?, chatInfo: ChatInfo.ContactConnection painterResource(MR.images.ic_delete), onClick = { deleteContactConnectionAlert(rhId, chatInfo.contactConnection, chatModel) { - if (chatModel.chatId.value == null) { - ModalManager.center.closeModals() - ModalManager.end.closeModals() - } + chatModel.dismissConnReqView(chatInfo.contactConnection.id) } showMenu.value = false }, @@ -586,7 +627,7 @@ fun contactRequestAlertDialog(rhId: Long?, contactRequest: ChatInfo.ContactReque } fun acceptContactRequest(rhId: Long?, incognito: Boolean, apiId: Long, contactRequest: ChatInfo.ContactRequest?, isCurrentUser: Boolean, chatModel: ChatModel) { - withApi { + withBGApi { val contact = chatModel.controller.apiAcceptContactRequest(rhId, incognito, apiId) if (contact != null && isCurrentUser && contactRequest != null) { val chat = Chat(remoteHostId = rhId, ChatInfo.Direct(contact), listOf()) @@ -596,7 +637,7 @@ fun acceptContactRequest(rhId: Long?, incognito: Boolean, apiId: Long, contactRe } fun rejectContactRequest(rhId: Long?, contactRequest: ChatInfo.ContactRequest, chatModel: ChatModel) { - withApi { + withBGApi { chatModel.controller.apiRejectContactRequest(rhId, contactRequest.apiId) chatModel.removeChat(rhId, contactRequest.id) } @@ -611,7 +652,7 @@ fun deleteContactConnectionAlert(rhId: Long?, connection: PendingContactConnecti ), confirmText = generalGetString(MR.strings.delete_verb), onConfirm = { - withApi { + withBGApi { AlertManager.shared.hideAlert() if (chatModel.controller.apiDeleteChat(rhId, ChatType.ContactConnection, connection.apiId)) { chatModel.removeChat(rhId, connection.id) @@ -630,7 +671,7 @@ fun pendingContactAlertDialog(rhId: Long?, chatInfo: ChatInfo, chatModel: ChatMo text = generalGetString(MR.strings.alert_text_connection_pending_they_need_to_be_online_can_delete_and_retry), confirmText = generalGetString(MR.strings.button_delete_contact), onConfirm = { - withApi { + withBGApi { val r = chatModel.controller.apiDeleteChat(rhId, chatInfo.chatType, chatInfo.apiId) if (r) { chatModel.removeChat(rhId, chatInfo.id) @@ -659,7 +700,7 @@ fun askCurrentOrIncognitoProfileConnectContactViaAddress( Column { SectionItemView({ AlertManager.privacySensitive.hideAlert() - withApi { + withBGApi { close?.invoke() val ok = connectContactViaAddress(chatModel, rhId, contact.contactId, incognito = false) if (ok && openChat) { @@ -671,7 +712,7 @@ fun askCurrentOrIncognitoProfileConnectContactViaAddress( } SectionItemView({ AlertManager.privacySensitive.hideAlert() - withApi { + withBGApi { close?.invoke() val ok = connectContactViaAddress(chatModel, rhId, contact.contactId, incognito = true) if (ok && openChat) { @@ -712,7 +753,7 @@ fun acceptGroupInvitationAlertDialog(rhId: Long?, groupInfo: GroupInfo, chatMode text = generalGetString(MR.strings.you_are_invited_to_group_join_to_connect_with_group_members), confirmText = if (groupInfo.membership.memberIncognito) generalGetString(MR.strings.join_group_incognito_button) else generalGetString(MR.strings.join_group_button), onConfirm = { - withApi { + withBGApi { inProgress?.value = true chatModel.controller.apiJoinGroup(rhId, groupInfo.groupId) inProgress?.value = false @@ -733,7 +774,7 @@ fun cantInviteIncognitoAlert() { } fun deleteGroup(rhId: Long?, groupInfo: GroupInfo, chatModel: ChatModel) { - withApi { + withBGApi { val r = chatModel.controller.apiDeleteChat(rhId, ChatType.Group, groupInfo.apiId) if (r) { chatModel.removeChat(rhId, groupInfo.id) @@ -774,7 +815,7 @@ fun updateChatSettings(chat: Chat, chatSettings: ChatSettings, chatModel: ChatMo } else -> null } - withApi { + withBGApi { val res = when (newChatInfo) { is ChatInfo.Direct -> with(newChatInfo) { chatModel.controller.apiSetSettings(chat.remoteHostId, chatType, apiId, contact.chatSettings) @@ -803,8 +844,9 @@ expect fun ChatListNavLinkLayout( click: () -> Unit, dropdownMenuItems: (@Composable () -> Unit)?, showMenu: MutableState<Boolean>, - stopped: Boolean, - selectedChat: State<Boolean> + disabled: Boolean, + selectedChat: State<Boolean>, + nextChatSelected: State<Boolean>, ) @Preview/*( @@ -836,7 +878,7 @@ fun PreviewChatListNavLinkDirect() { null, null, null, - stopped = false, + disabled = false, linkMode = SimplexLinkMode.DESCRIPTION, inProgress = false, progressByTimeout = false @@ -845,8 +887,9 @@ fun PreviewChatListNavLinkDirect() { click = {}, dropdownMenuItems = null, showMenu = remember { mutableStateOf(false) }, - stopped = false, - selectedChat = remember { mutableStateOf(false) } + disabled = false, + selectedChat = remember { mutableStateOf(false) }, + nextChatSelected = remember { mutableStateOf(false) } ) } } @@ -880,7 +923,7 @@ fun PreviewChatListNavLinkGroup() { null, null, null, - stopped = false, + disabled = false, linkMode = SimplexLinkMode.DESCRIPTION, inProgress = false, progressByTimeout = false @@ -889,8 +932,9 @@ fun PreviewChatListNavLinkGroup() { click = {}, dropdownMenuItems = null, showMenu = remember { mutableStateOf(false) }, - stopped = false, - selectedChat = remember { mutableStateOf(false) } + disabled = false, + selectedChat = remember { mutableStateOf(false) }, + nextChatSelected = remember { mutableStateOf(false) } ) } } @@ -910,8 +954,9 @@ fun PreviewChatListNavLinkContactRequest() { click = {}, dropdownMenuItems = null, showMenu = remember { mutableStateOf(false) }, - stopped = false, - selectedChat = remember { mutableStateOf(false) } + disabled = false, + selectedChat = remember { mutableStateOf(false) }, + nextChatSelected = remember { mutableStateOf(false) } ) } } diff --git a/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/views/chatlist/ChatListView.kt b/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/views/chatlist/ChatListView.kt index cf12727d74..3a47d062ac 100644 --- a/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/views/chatlist/ChatListView.kt +++ b/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/views/chatlist/ChatListView.kt @@ -10,11 +10,15 @@ import androidx.compose.runtime.* import androidx.compose.runtime.saveable.rememberSaveable import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier +import androidx.compose.ui.focus.* import androidx.compose.ui.graphics.* import androidx.compose.ui.text.font.FontStyle +import androidx.compose.ui.platform.* +import androidx.compose.ui.text.TextRange import dev.icerock.moko.resources.compose.painterResource import dev.icerock.moko.resources.compose.stringResource import androidx.compose.ui.text.font.FontWeight +import androidx.compose.ui.text.input.TextFieldValue import androidx.compose.ui.unit.* import chat.simplex.common.SettingsViewState import chat.simplex.common.model.* @@ -29,6 +33,7 @@ import chat.simplex.common.views.newchat.* import chat.simplex.res.MR import kotlinx.coroutines.* import kotlinx.coroutines.flow.MutableStateFlow +import kotlinx.coroutines.flow.distinctUntilChanged import java.net.URI @Composable @@ -60,20 +65,22 @@ fun ChatListView(chatModel: ChatModel, settingsState: SettingsViewState, setPerf } } val endPadding = if (appPlatform.isDesktop) 56.dp else 0.dp - var searchInList by rememberSaveable { mutableStateOf("") } + val searchText = rememberSaveable(stateSaver = TextFieldValue.Saver) { mutableStateOf(TextFieldValue("")) } val scope = rememberCoroutineScope() val (userPickerState, scaffoldState ) = settingsState - Scaffold(topBar = { Box(Modifier.padding(end = endPadding)) { ChatListToolbar(chatModel, scaffoldState.drawerState, userPickerState, stopped) { searchInList = it.trim() } } }, + Scaffold(topBar = { Box(Modifier.padding(end = endPadding)) { ChatListToolbar(searchText, scaffoldState.drawerState, userPickerState, stopped)} }, scaffoldState = scaffoldState, drawerContent = { tryOrShowError("Settings", error = { ErrorSettingsView() }) { SettingsView(chatModel, setPerformLA, scaffoldState.drawerState) } }, + contentColor = LocalContentColor.current, + drawerContentColor = LocalContentColor.current, drawerScrimColor = MaterialTheme.colors.onSurface.copy(alpha = if (isInDarkTheme()) 0.16f else 0.32f), drawerGesturesEnabled = appPlatform.isAndroid, floatingActionButton = { - if (searchInList.isEmpty() && !chatModel.desktopNoUserNoRemote) { + if (searchText.value.text.isEmpty() && !chatModel.desktopNoUserNoRemote && chatModel.chatRunning.value == true) { FloatingActionButton( onClick = { if (!stopped) { @@ -96,24 +103,24 @@ fun ChatListView(chatModel: ChatModel, settingsState: SettingsViewState, setPerf } ) { Box(Modifier.padding(it).padding(end = endPadding)) { - Column( + Box( modifier = Modifier .fillMaxSize() ) { - if (chatModel.chats.isNotEmpty()) { - ChatList(chatModel, search = searchInList) - } else if (!chatModel.switchingUsersAndHosts.value && !chatModel.desktopNoUserNoRemote) { - Box(Modifier.fillMaxSize()) { - if (!stopped && !newChatSheetState.collectAsState().value.isVisible()) { - OnboardingButtons(showNewChatSheet) - } - Text(stringResource(MR.strings.you_have_no_chats), Modifier.align(Alignment.Center), color = MaterialTheme.colors.secondary) + if (!chatModel.desktopNoUserNoRemote) { + ChatList(chatModel, searchText = searchText) + } + if (chatModel.chats.isEmpty() && !chatModel.switchingUsersAndHosts.value && !chatModel.desktopNoUserNoRemote) { + Text(stringResource( + if (chatModel.chatRunning.value == null) MR.strings.loading_chats else MR.strings.you_have_no_chats), Modifier.align(Alignment.Center), color = MaterialTheme.colors.secondary) + if (!stopped && !newChatSheetState.collectAsState().value.isVisible() && chatModel.chatRunning.value == true && searchText.value.text.isEmpty()) { + OnboardingButtons(showNewChatSheet) } } } } } - if (searchInList.isEmpty()) { + if (searchText.value.text.isEmpty()) { DesktopActiveCallOverlayLayout(newChatSheetState) // TODO disable this button and sheet for the duration of the switch tryOrShowError("NewChatSheet", error = {}) { @@ -168,20 +175,8 @@ private fun ConnectButton(text: String, onClick: () -> Unit) { } @Composable -private fun ChatListToolbar(chatModel: ChatModel, drawerState: DrawerState, userPickerState: MutableStateFlow<AnimatedViewState>, stopped: Boolean, onSearchValueChanged: (String) -> Unit) { - var showSearch by rememberSaveable { mutableStateOf(false) } - val hideSearchOnBack = { onSearchValueChanged(""); showSearch = false } - if (showSearch) { - BackHandler(onBack = hideSearchOnBack) - } +private fun ChatListToolbar(searchInList: State<TextFieldValue>, drawerState: DrawerState, userPickerState: MutableStateFlow<AnimatedViewState>, stopped: Boolean) { val barButtons = arrayListOf<@Composable RowScope.() -> Unit>() - if (chatModel.chats.size > 0) { - barButtons.add { - IconButton({ showSearch = true }) { - Icon(painterResource(MR.images.ic_search_500), stringResource(MR.strings.search_verb), tint = MaterialTheme.colors.primary) - } - } - } if (stopped) { barButtons.add { IconButton(onClick = { @@ -201,9 +196,7 @@ private fun ChatListToolbar(chatModel: ChatModel, drawerState: DrawerState, user val scope = rememberCoroutineScope() DefaultTopAppBar( navigationButton = { - if (showSearch) { - NavigationButtonBack(hideSearchOnBack) - } else if (chatModel.users.isEmpty() && !chatModel.desktopNoUserNoRemote) { + if (chatModel.users.isEmpty() && !chatModel.desktopNoUserNoRemote) { NavigationButtonMenu { scope.launch { if (drawerState.isOpen) drawerState.close() else drawerState.open() } } } else { val users by remember { derivedStateOf { chatModel.users.filter { u -> u.user.activeUser || !u.user.hidden } } } @@ -227,13 +220,18 @@ private fun ChatListToolbar(chatModel: ChatModel, drawerState: DrawerState, user fontWeight = FontWeight.SemiBold, ) if (chatModel.chats.size > 0) { - ToggleFilterButton() + val enabled = remember { derivedStateOf { searchInList.value.text.isEmpty() } } + if (enabled.value) { + ToggleFilterEnabledButton() + } else { + ToggleFilterDisabledButton() + } } } }, onTitleClick = null, - showSearch = showSearch, - onSearchValueChanged = onSearchValueChanged, + showSearch = false, + onSearchValueChanged = {}, buttons = barButtons ) Divider(Modifier.padding(top = AppBarHeight)) @@ -246,7 +244,8 @@ fun UserProfileButton(image: String?, allRead: Boolean, onButtonClicked: () -> U Box { ProfileImage( image = image, - size = 37.dp + size = 37.dp, + color = MaterialTheme.colors.secondaryVariant.mixWith(MaterialTheme.colors.onBackground, 0.97f) ) if (!allRead) { unreadBadge() @@ -281,7 +280,7 @@ private fun BoxScope.unreadBadge(text: String? = "") { } @Composable -private fun ToggleFilterButton() { +private fun ToggleFilterEnabledButton() { val pref = remember { ChatController.appPrefs.showUnreadAndFavorites } IconButton(onClick = { pref.set(!pref.get()) }) { Icon( @@ -290,7 +289,7 @@ private fun ToggleFilterButton() { tint = if (pref.state.value) MaterialTheme.colors.background else MaterialTheme.colors.primary, modifier = Modifier .padding(3.dp) - .background(color = if (pref.state.value) MaterialTheme.colors.primary else MaterialTheme.colors.background, shape = RoundedCornerShape(50)) + .background(color = if (pref.state.value) MaterialTheme.colors.primary else Color.Unspecified, shape = RoundedCornerShape(50)) .border(width = 1.dp, color = MaterialTheme.colors.primary, shape = RoundedCornerShape(50)) .padding(3.dp) .size(16.dp) @@ -298,6 +297,22 @@ private fun ToggleFilterButton() { } } +@Composable +private fun ToggleFilterDisabledButton() { + IconButton({}, enabled = false) { + Icon( + painterResource(MR.images.ic_filter_list), + null, + tint = MaterialTheme.colors.secondary, + modifier = Modifier + .padding(3.dp) + .border(width = 1.dp, color = MaterialTheme.colors.secondary, shape = RoundedCornerShape(50)) + .padding(3.dp) + .size(16.dp) + ) + } +} + @Composable expect fun DesktopActiveCallOverlayLayout(newChatSheetState: MutableStateFlow<AnimatedViewState>) @@ -306,12 +321,116 @@ fun connectIfOpenedViaUri(rhId: Long?, uri: URI, chatModel: ChatModel) { if (chatModel.currentUser.value == null) { chatModel.appOpenUrl.value = rhId to uri } else { - withApi { - planAndConnect(chatModel, rhId, uri, incognito = null, close = null) + withBGApi { + planAndConnect(rhId, uri, incognito = null, close = null) } } } +@Composable +private fun ChatListSearchBar(listState: LazyListState, searchText: MutableState<TextFieldValue>, searchShowingSimplexLink: MutableState<Boolean>, searchChatFilteredBySimplexLink: MutableState<String?>) { + Row(verticalAlignment = Alignment.CenterVertically) { + val focusRequester = remember { FocusRequester() } + var focused by remember { mutableStateOf(false) } + Icon(painterResource(MR.images.ic_search), null, Modifier.padding(horizontal = DEFAULT_PADDING_HALF), tint = MaterialTheme.colors.secondary) + SearchTextField( + Modifier.weight(1f).onFocusChanged { focused = it.hasFocus }.focusRequester(focusRequester), + placeholder = stringResource(MR.strings.search_or_paste_simplex_link), + alwaysVisible = true, + searchText = searchText, + enabled = !remember { searchShowingSimplexLink }.value, + trailingContent = null, + ) { + searchText.value = searchText.value.copy(it) + } + val hasText = remember { derivedStateOf { searchText.value.text.isNotEmpty() } } + if (hasText.value) { + val hideSearchOnBack: () -> Unit = { searchText.value = TextFieldValue() } + BackHandler(onBack = hideSearchOnBack) + KeyChangeEffect(chatModel.currentRemoteHost.value) { + hideSearchOnBack() + } + } else { + Row { + val padding = if (appPlatform.isDesktop) 0.dp else 7.dp + val clipboard = LocalClipboardManager.current + val clipboardHasText = remember(focused) { chatModel.clipboardHasText }.value + if (clipboardHasText) { + IconButton( + onClick = { searchText.value = searchText.value.copy(clipboard.getText()?.text ?: return@IconButton) }, + Modifier.size(30.dp).desktopPointerHoverIconHand() + ) { + Icon(painterResource(MR.images.ic_article), null, tint = MaterialTheme.colors.secondary) + } + } + Spacer(Modifier.width(padding)) + IconButton( + onClick = { + val fixedRhId = chatModel.currentRemoteHost.value + ModalManager.center.closeModals() + ModalManager.center.showModalCloseable { close -> + NewChatView(fixedRhId, selection = NewChatOption.CONNECT, showQRCodeScanner = true, close = close) + } + }, + Modifier.size(30.dp).desktopPointerHoverIconHand() + ) { + Icon(painterResource(MR.images.ic_qr_code), null, tint = MaterialTheme.colors.secondary) + } + Spacer(Modifier.width(padding)) + } + } + val focusManager = LocalFocusManager.current + val keyboardState = getKeyboardState() + LaunchedEffect(keyboardState.value) { + if (keyboardState.value == KeyboardState.Closed && focused) { + focusManager.clearFocus() + } + } + val view = LocalMultiplatformView() + LaunchedEffect(Unit) { + snapshotFlow { searchText.value.text } + .distinctUntilChanged() + .collect { + val link = strHasSingleSimplexLink(it.trim()) + if (link != null) { + // if SimpleX link is pasted, show connection dialogue + hideKeyboard(view) + if (link.format is Format.SimplexLink) { + val linkText = link.simplexLinkText(link.format.linkType, link.format.smpHosts) + searchText.value = searchText.value.copy(linkText, selection = TextRange.Zero) + } + searchShowingSimplexLink.value = true + searchChatFilteredBySimplexLink.value = null + connect(link.text, searchChatFilteredBySimplexLink) { searchText.value = TextFieldValue() } + } else if (!searchShowingSimplexLink.value || it.isEmpty()) { + if (it.isNotEmpty()) { + // if some other text is pasted, enter search mode + focusRequester.requestFocus() + } else if (listState.layoutInfo.totalItemsCount > 0) { + listState.scrollToItem(0) + } + searchShowingSimplexLink.value = false + searchChatFilteredBySimplexLink.value = null + } + } + } + } +} + +private fun connect(link: String, searchChatFilteredBySimplexLink: MutableState<String?>, cleanup: (() -> Unit)?) { + withBGApi { + planAndConnect( + chatModel.remoteHostId(), + URI.create(link), + incognito = null, + filterKnownContact = { searchChatFilteredBySimplexLink.value = it.id }, + filterKnownGroup = { searchChatFilteredBySimplexLink.value = it.id }, + close = null, + cleanup = cleanup, + ) + } +} + @Composable private fun ErrorSettingsView() { Box(Modifier.fillMaxSize(), contentAlignment = Alignment.Center) { @@ -322,7 +441,7 @@ private fun ErrorSettingsView() { private var lazyListState = 0 to 0 @Composable -private fun ChatList(chatModel: ChatModel, search: String) { +private fun ChatList(chatModel: ChatModel, searchText: MutableState<TextFieldValue>) { val listState = rememberLazyListState(lazyListState.first, lazyListState.second) DisposableEffect(Unit) { onDispose { lazyListState = listState.firstVisibleItemIndex to listState.firstVisibleItemScrollOffset } @@ -332,44 +451,78 @@ private fun ChatList(chatModel: ChatModel, search: String) { // In some not always reproducible situations this code produce IndexOutOfBoundsException on Compose's side // which is related to [derivedStateOf]. Using safe alternative instead // val chats by remember(search, showUnreadAndFavorites) { derivedStateOf { filteredChats(showUnreadAndFavorites, search, allChats.toList()) } } - val chats = filteredChats(showUnreadAndFavorites, search, allChats.toList()) + val searchShowingSimplexLink = remember { mutableStateOf(false) } + val searchChatFilteredBySimplexLink = remember { mutableStateOf<String?>(null) } + val chats = filteredChats(showUnreadAndFavorites, searchShowingSimplexLink, searchChatFilteredBySimplexLink, searchText.value.text, allChats.toList()) LazyColumn( - modifier = Modifier.fillMaxWidth(), + Modifier.fillMaxWidth(), listState ) { - items(chats) { chat -> - ChatListNavLinkView(chat, chatModel) + stickyHeader { + Column( + Modifier + .offset { + val y = if (searchText.value.text.isEmpty()) { + if (listState.firstVisibleItemIndex == 0) -listState.firstVisibleItemScrollOffset else -1000 + } else { + 0 + } + IntOffset(0, y) + } + .background(MaterialTheme.colors.background) + ) { + ChatListSearchBar(listState, searchText, searchShowingSimplexLink, searchChatFilteredBySimplexLink) + Divider() + } + } + itemsIndexed(chats) { index, chat -> + val nextChatSelected = remember(chat.id, chats) { derivedStateOf { + chatModel.chatId.value != null && chats.getOrNull(index + 1)?.id == chatModel.chatId.value + } } + ChatListNavLinkView(chat, nextChatSelected) } } - if (chats.isEmpty() && !chatModel.chats.isEmpty()) { + if (chats.isEmpty() && chatModel.chats.isNotEmpty()) { Box(Modifier.fillMaxSize(), contentAlignment = Alignment.Center) { Text(generalGetString(MR.strings.no_filtered_chats), color = MaterialTheme.colors.secondary) } } } -private fun filteredChats(showUnreadAndFavorites: Boolean, searchText: String, chats: List<Chat>): List<Chat> { - val s = searchText.trim().lowercase() - return if (s.isEmpty() && !showUnreadAndFavorites) - chats - else { - chats.filter { chat -> - when (val cInfo = chat.chatInfo) { - is ChatInfo.Direct -> if (s.isEmpty()) { - filtered(chat) - } else { - (viewNameContains(cInfo, s) || - cInfo.contact.profile.displayName.lowercase().contains(s) || - cInfo.contact.fullName.lowercase().contains(s)) +private fun filteredChats( + showUnreadAndFavorites: Boolean, + searchShowingSimplexLink: State<Boolean>, + searchChatFilteredBySimplexLink: State<String?>, + searchText: String, + chats: List<Chat> +): List<Chat> { + val linkChatId = searchChatFilteredBySimplexLink.value + return if (linkChatId != null) { + chats.filter { it.id == linkChatId } + } else { + val s = if (searchShowingSimplexLink.value) "" else searchText.trim().lowercase() + if (s.isEmpty() && !showUnreadAndFavorites) + chats + else { + chats.filter { chat -> + when (val cInfo = chat.chatInfo) { + is ChatInfo.Direct -> if (s.isEmpty()) { + chat.id == chatModel.chatId.value || filtered(chat) + } else { + (viewNameContains(cInfo, s) || + cInfo.contact.profile.displayName.lowercase().contains(s) || + cInfo.contact.fullName.lowercase().contains(s)) + } + is ChatInfo.Group -> if (s.isEmpty()) { + chat.id == chatModel.chatId.value || filtered(chat) || cInfo.groupInfo.membership.memberStatus == GroupMemberStatus.MemInvited + } else { + viewNameContains(cInfo, s) + } + is ChatInfo.Local -> s.isEmpty() || viewNameContains(cInfo, s) + is ChatInfo.ContactRequest -> s.isEmpty() || viewNameContains(cInfo, s) + is ChatInfo.ContactConnection -> (s.isNotEmpty() && cInfo.contactConnection.localAlias.lowercase().contains(s)) || (s.isEmpty() && chat.id == chatModel.chatId.value) + is ChatInfo.InvalidJSON -> chat.id == chatModel.chatId.value } - is ChatInfo.Group -> if (s.isEmpty()) { - (filtered(chat) || cInfo.groupInfo.membership.memberStatus == GroupMemberStatus.MemInvited) - } else { - viewNameContains(cInfo, s) - } - is ChatInfo.ContactRequest -> s.isEmpty() || viewNameContains(cInfo, s) - is ChatInfo.ContactConnection -> s.isNotEmpty() && cInfo.contactConnection.localAlias.lowercase().contains(s) - is ChatInfo.InvalidJSON -> false } } } diff --git a/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/views/chatlist/ChatPreviewView.kt b/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/views/chatlist/ChatPreviewView.kt index af1f49a088..08e95f391a 100644 --- a/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/views/chatlist/ChatPreviewView.kt +++ b/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/views/chatlist/ChatPreviewView.kt @@ -25,6 +25,7 @@ import chat.simplex.common.views.chat.item.MarkdownText import chat.simplex.common.views.helpers.* import chat.simplex.common.model.* import chat.simplex.common.model.GroupInfo +import chat.simplex.common.platform.chatModel import chat.simplex.res.MR import dev.icerock.moko.resources.ImageResource @@ -36,7 +37,7 @@ fun ChatPreviewView( chatModelDraftChatId: ChatId?, currentUserProfileDisplayName: String?, contactNetworkStatus: NetworkStatus?, - stopped: Boolean, + disabled: Boolean, linkMode: SimplexLinkMode, inProgress: Boolean, progressByTimeout: Boolean @@ -127,24 +128,35 @@ fun ChatPreviewView( @Composable fun chatPreviewTitle() { + val deleting by remember(disabled, chat.id) { mutableStateOf(chatModel.deletedChats.value.contains(chat.remoteHostId to chat.chatInfo.id)) } when (cInfo) { is ChatInfo.Direct -> Row(verticalAlignment = Alignment.CenterVertically) { if (cInfo.contact.verified) { VerifiedIcon() } - chatPreviewTitleText() + chatPreviewTitleText( + if (deleting) + MaterialTheme.colors.secondary + else + Color.Unspecified + ) } is ChatInfo.Group -> when (cInfo.groupInfo.membership.memberStatus) { GroupMemberStatus.MemInvited -> chatPreviewTitleText( - if (inProgress) + if (inProgress || deleting) MaterialTheme.colors.secondary else if (chat.chatInfo.incognito) Indigo else MaterialTheme.colors.primary ) GroupMemberStatus.MemAccepted -> chatPreviewTitleText(MaterialTheme.colors.secondary) - else -> chatPreviewTitleText() + else -> chatPreviewTitleText( + if (deleting) + MaterialTheme.colors.secondary + else + Color.Unspecified + ) } else -> chatPreviewTitleText() } @@ -173,6 +185,7 @@ fun ChatPreviewView( cInfo is ChatInfo.Group && !ci.chatDir.sent -> ci.memberDisplayName else -> null }, + toggleSecrets = false, linkMode = linkMode, senderBold = true, maxLines = 2, @@ -292,7 +305,7 @@ fun ChatPreviewView( color = Color.White, fontSize = 11.sp, modifier = Modifier - .background(if (stopped || showNtfsIcon) MaterialTheme.colors.secondary else MaterialTheme.colors.primaryVariant, shape = CircleShape) + .background(if (disabled || showNtfsIcon) MaterialTheme.colors.secondary else MaterialTheme.colors.primaryVariant, shape = CircleShape) .badgeLayout() .padding(horizontal = 3.dp) .padding(vertical = 1.dp) @@ -373,6 +386,6 @@ fun unreadCountStr(n: Int): String { @Composable fun PreviewChatPreviewView() { SimpleXTheme { - ChatPreviewView(Chat.sampleData, true, null, null, "", contactNetworkStatus = NetworkStatus.Connected(), stopped = false, linkMode = SimplexLinkMode.DESCRIPTION, inProgress = false, progressByTimeout = false) + ChatPreviewView(Chat.sampleData, true, null, null, "", contactNetworkStatus = NetworkStatus.Connected(), disabled = false, linkMode = SimplexLinkMode.DESCRIPTION, inProgress = false, progressByTimeout = false) } } diff --git a/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/views/chatlist/ShareListNavLinkView.kt b/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/views/chatlist/ShareListNavLinkView.kt index ad8f93990f..1de1e40afb 100644 --- a/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/views/chatlist/ShareListNavLinkView.kt +++ b/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/views/chatlist/ShareListNavLinkView.kt @@ -9,9 +9,10 @@ import androidx.compose.ui.Modifier import androidx.compose.ui.graphics.Color import androidx.compose.ui.text.style.TextOverflow import androidx.compose.ui.unit.dp -import chat.simplex.common.ui.theme.Indigo import chat.simplex.common.views.helpers.ProfileImage import chat.simplex.common.model.* +import chat.simplex.common.ui.theme.* +import chat.simplex.res.MR @Composable fun ShareListNavLinkView(chat: Chat, chatModel: ChatModel) { @@ -29,6 +30,12 @@ fun ShareListNavLinkView(chat: Chat, chatModel: ChatModel) { click = { groupChatAction(chat.remoteHostId, chat.chatInfo.groupInfo, chatModel) }, stopped ) + is ChatInfo.Local -> + ShareListNavLinkLayout( + chatLinkPreview = { SharePreviewView(chat) }, + click = { noteFolderChatAction(chat.remoteHostId, chat.chatInfo.noteFolder) }, + stopped + ) is ChatInfo.ContactRequest, is ChatInfo.ContactConnection, is ChatInfo.InvalidJSON -> {} } } @@ -56,7 +63,11 @@ private fun SharePreviewView(chat: Chat) { verticalAlignment = Alignment.CenterVertically, horizontalArrangement = Arrangement.spacedBy(4.dp) ) { - ProfileImage(size = 46.dp, chat.chatInfo.image) + if (chat.chatInfo is ChatInfo.Local) { + ProfileImage(size = 46.dp, null, icon = MR.images.ic_folder_filled, color = NoteFolderIconColor) + } else { + ProfileImage(size = 46.dp, chat.chatInfo.image) + } Text( chat.chatInfo.chatViewName, maxLines = 1, overflow = TextOverflow.Ellipsis, color = if (chat.chatInfo.incognito) Indigo else Color.Unspecified diff --git a/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/views/chatlist/ShareListView.kt b/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/views/chatlist/ShareListView.kt index ac8331007e..b1e87823c8 100644 --- a/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/views/chatlist/ShareListView.kt +++ b/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/views/chatlist/ShareListView.kt @@ -30,6 +30,8 @@ fun ShareListView(chatModel: ChatModel, settingsState: SettingsViewState, stoppe val endPadding = if (appPlatform.isDesktop) 56.dp else 0.dp Scaffold( Modifier.padding(end = endPadding), + contentColor = LocalContentColor.current, + drawerContentColor = LocalContentColor.current, scaffoldState = scaffoldState, topBar = { Column { ShareListToolbar(chatModel, userPickerState, stopped) { searchInList = it.trim() } } }, ) { diff --git a/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/views/chatlist/UserPicker.kt b/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/views/chatlist/UserPicker.kt index d87c05a913..23272fcc0c 100644 --- a/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/views/chatlist/UserPicker.kt +++ b/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/views/chatlist/UserPicker.kt @@ -31,9 +31,8 @@ import chat.simplex.common.views.remote.* import chat.simplex.common.views.usersettings.doWithAuth import chat.simplex.res.MR import dev.icerock.moko.resources.compose.stringResource -import kotlinx.coroutines.delay +import kotlinx.coroutines.* import kotlinx.coroutines.flow.* -import kotlinx.coroutines.launch import kotlin.math.roundToInt @Composable @@ -116,14 +115,19 @@ fun UserPicker( } } LaunchedEffect(Unit) { - controller.reloadRemoteHosts() + // Controller.ctrl can be null when self-destructing activates + if (controller.ctrl != null && controller.ctrl != -1L) { + withBGApi { + controller.reloadRemoteHosts() + } + } } val UsersView: @Composable ColumnScope.() -> Unit = { users.forEach { u -> UserProfilePickerItem(u.user, u.unreadCount, openSettings = settingsClicked) { userPickerState.value = AnimatedViewState.HIDING if (!u.user.activeUser) { - scope.launch { + withBGApi { controller.showProgressIfNeeded { ModalManager.closeAllModalsEverywhere() chatModel.controller.changeActiveUser(u.user.remoteHostId, u.user.userId, null) @@ -209,26 +213,29 @@ fun UserPicker( userPickerState.value = AnimatedViewState.GONE } Divider(Modifier.requiredHeight(1.dp)) - } else if (remoteHosts.isEmpty()) { - LinkAMobilePickerItem { - ModalManager.start.showModal { - ConnectMobileView() + } else { + if (remoteHosts.isEmpty()) { + LinkAMobilePickerItem { + ModalManager.start.showModal { + ConnectMobileView() + } + userPickerState.value = AnimatedViewState.GONE } - userPickerState.value = AnimatedViewState.GONE + Divider(Modifier.requiredHeight(1.dp)) } - Divider(Modifier.requiredHeight(1.dp)) - } else if (chatModel.desktopNoUserNoRemote) { - CreateInitialProfile { - doWithAuth(generalGetString(MR.strings.auth_open_chat_profiles), generalGetString(MR.strings.auth_log_in_using_credential)) { - ModalManager.center.showModalCloseable { close -> - LaunchedEffect(Unit) { - userPickerState.value = AnimatedViewState.HIDING + if (chatModel.desktopNoUserNoRemote) { + CreateInitialProfile { + doWithAuth(generalGetString(MR.strings.auth_open_chat_profiles), generalGetString(MR.strings.auth_log_in_using_credential)) { + ModalManager.center.showModalCloseable { close -> + LaunchedEffect(Unit) { + userPickerState.value = AnimatedViewState.HIDING + } + CreateProfile(chat.simplex.common.platform.chatModel, close) } - CreateProfile(chat.simplex.common.platform.chatModel, close) } } + Divider(Modifier.requiredHeight(1.dp)) } - Divider(Modifier.requiredHeight(1.dp)) } if (showSettings) { SettingsPickerItem(settingsClicked) @@ -241,23 +248,31 @@ fun UserPicker( } @Composable -fun UserProfilePickerItem(u: User, unreadCount: Int = 0, onLongClick: () -> Unit = {}, openSettings: () -> Unit = {}, onClick: () -> Unit) { +fun UserProfilePickerItem( + u: User, + unreadCount: Int = 0, + enabled: Boolean = chatModel.chatRunning.value == true || chatModel.connectedToRemote, + onLongClick: () -> Unit = {}, + openSettings: () -> Unit = {}, + onClick: () -> Unit +) { Row( Modifier .fillMaxWidth() .sizeIn(minHeight = 46.dp) .combinedClickable( + enabled = enabled, onClick = if (u.activeUser) openSettings else onClick, onLongClick = onLongClick, interactionSource = remember { MutableInteractionSource() }, indication = if (!u.activeUser) LocalIndication.current else null ) - .onRightClick { onLongClick() } + .onRightClick { if (enabled) onLongClick() } .padding(start = DEFAULT_PADDING_HALF, end = DEFAULT_PADDING), horizontalArrangement = Arrangement.SpaceBetween, verticalAlignment = Alignment.CenterVertically ) { - UserProfileRow(u) + UserProfileRow(u, enabled) if (u.activeUser) { Icon(painterResource(MR.images.ic_done_filled), null, Modifier.size(20.dp), tint = MaterialTheme.colors.onBackground) } else if (u.hidden) { @@ -285,7 +300,7 @@ fun UserProfilePickerItem(u: User, unreadCount: Int = 0, onLongClick: () -> Unit } @Composable -fun UserProfileRow(u: User) { +fun UserProfileRow(u: User, enabled: Boolean = chatModel.chatRunning.value == true || chatModel.connectedToRemote) { Row( Modifier .widthIn(max = windowWidth() * 0.7f) @@ -300,7 +315,7 @@ fun UserProfileRow(u: User) { u.displayName, modifier = Modifier .padding(start = 10.dp, end = 8.dp), - color = if (isInDarkTheme()) MenuTextColorDark else Color.Black, + color = if (enabled) MenuTextColor else MaterialTheme.colors.secondary, fontWeight = if (u.activeUser) FontWeight.Medium else FontWeight.Normal ) } @@ -343,7 +358,7 @@ fun RemoteHostRow(h: RemoteHostInfo) { Text( h.hostDeviceName, modifier = Modifier.padding(start = 26.dp, end = 8.dp), - color = if (h.activeHost) MaterialTheme.colors.onBackground else if (isInDarkTheme()) MenuTextColorDark else Color.Black, + color = if (h.activeHost) MaterialTheme.colors.onBackground else MenuTextColor, fontSize = 14.sp, ) } @@ -384,7 +399,7 @@ fun LocalDeviceRow(active: Boolean) { Text( stringResource(MR.strings.this_device), modifier = Modifier.padding(start = 26.dp, end = 8.dp), - color = if (active) MaterialTheme.colors.onBackground else if (isInDarkTheme()) MenuTextColorDark else Color.Black, + color = if (active) MaterialTheme.colors.onBackground else MenuTextColor, fontSize = 14.sp, ) } @@ -396,7 +411,7 @@ private fun UseFromDesktopPickerItem(onClick: () -> Unit) { val text = generalGetString(MR.strings.settings_section_title_use_from_desktop).lowercase().capitalize(Locale.current) Icon(painterResource(MR.images.ic_desktop), text, Modifier.size(20.dp), tint = MaterialTheme.colors.onBackground) Spacer(Modifier.width(DEFAULT_PADDING + 6.dp)) - Text(text, color = if (isInDarkTheme()) MenuTextColorDark else Color.Black) + Text(text, color = MenuTextColor) } } @@ -406,7 +421,7 @@ private fun LinkAMobilePickerItem(onClick: () -> Unit) { val text = generalGetString(MR.strings.link_a_mobile) Icon(painterResource(MR.images.ic_smartphone_300), text, Modifier.size(20.dp), tint = MaterialTheme.colors.onBackground) Spacer(Modifier.width(DEFAULT_PADDING + 6.dp)) - Text(text, color = if (isInDarkTheme()) MenuTextColorDark else Color.Black) + Text(text, color = MenuTextColor) } } @@ -416,7 +431,7 @@ private fun CreateInitialProfile(onClick: () -> Unit) { val text = generalGetString(MR.strings.create_chat_profile) Icon(painterResource(MR.images.ic_manage_accounts), text, Modifier.size(20.dp), tint = MaterialTheme.colors.onBackground) Spacer(Modifier.width(DEFAULT_PADDING + 6.dp)) - Text(text, color = if (isInDarkTheme()) MenuTextColorDark else Color.Black) + Text(text, color = MenuTextColor) } } @@ -426,7 +441,7 @@ private fun SettingsPickerItem(onClick: () -> Unit) { val text = generalGetString(MR.strings.settings_section_title_settings).lowercase().capitalize(Locale.current) Icon(painterResource(MR.images.ic_settings), text, Modifier.size(20.dp), tint = MaterialTheme.colors.onBackground) Spacer(Modifier.width(DEFAULT_PADDING + 6.dp)) - Text(text, color = if (isInDarkTheme()) MenuTextColorDark else Color.Black) + Text(text, color = MenuTextColor) } } @@ -436,7 +451,7 @@ private fun CancelPickerItem(onClick: () -> Unit) { val text = generalGetString(MR.strings.cancel_verb) Icon(painterResource(MR.images.ic_close), text, Modifier.size(20.dp), tint = MaterialTheme.colors.onBackground) Spacer(Modifier.width(DEFAULT_PADDING + 6.dp)) - Text(text, color = if (isInDarkTheme()) MenuTextColorDark else Color.Black) + Text(text, color = MenuTextColor) } } diff --git a/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/views/database/ChatArchiveView.kt b/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/views/database/ChatArchiveView.kt index 8738db2df1..1e2f8420fd 100644 --- a/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/views/database/ChatArchiveView.kt +++ b/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/views/database/ChatArchiveView.kt @@ -34,7 +34,7 @@ fun ChatArchiveView(m: ChatModel, title: String, archiveName: String, archiveTim ChatArchiveLayout( title, archiveTime, - saveArchive = { withApi { saveArchiveLauncher.launch(archivePath.substringAfterLast(File.separator)) }}, + saveArchive = { withLongRunningApi { saveArchiveLauncher.launch(archivePath.substringAfterLast(File.separator)) }}, deleteArchiveAlert = { deleteArchiveAlert(m, archivePath) } ) } diff --git a/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/views/database/DatabaseEncryptionView.kt b/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/views/database/DatabaseEncryptionView.kt index e34f80a7ef..3cfd9e94b4 100644 --- a/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/views/database/DatabaseEncryptionView.kt +++ b/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/views/database/DatabaseEncryptionView.kt @@ -62,7 +62,7 @@ fun DatabaseEncryptionView(m: ChatModel) { initialRandomDBPassphrase, progressIndicator, onConfirmEncrypt = { - withApi { + withLongRunningApi(slow = 30_000, deadlock = 60_000) { encryptDatabase(currentKey, newKey, confirmNewKey, initialRandomDBPassphrase, useKeychain, storedKey, progressIndicator) } } @@ -233,13 +233,13 @@ fun resetFormAfterEncryption( storedKey: MutableState<Boolean>, stored: Boolean = false, ) { - m.chatDbEncrypted.value = true - initialRandomDBPassphrase.value = false - m.controller.appPrefs.initialRandomDBPassphrase.set(false) currentKey.value = "" newKey.value = "" confirmNewKey.value = "" storedKey.value = stored + m.chatDbEncrypted.value = true + initialRandomDBPassphrase.value = false + m.controller.appPrefs.initialRandomDBPassphrase.set(false) } fun setUseKeychain(value: Boolean, useKeychain: MutableState<Boolean>, prefs: AppPreferences) { @@ -392,12 +392,11 @@ suspend fun encryptDatabase( false } else -> { - prefs.initialRandomDBPassphrase.set(false) - initialRandomDBPassphrase.value = false - if (useKeychain.value) { - DatabaseUtils.ksDatabasePassword.set(newKey.value) - } + val new = newKey.value resetFormAfterEncryption(m, initialRandomDBPassphrase, currentKey, newKey, confirmNewKey, storedKey, useKeychain.value) + if (useKeychain.value) { + DatabaseUtils.ksDatabasePassword.set(new) + } operationEnded(m, progressIndicator) { AlertManager.shared.showAlertMsg(generalGetString(MR.strings.database_encrypted)) } diff --git a/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/views/database/DatabaseErrorView.kt b/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/views/database/DatabaseErrorView.kt index 22d69de1cc..0c208c06e8 100644 --- a/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/views/database/DatabaseErrorView.kt +++ b/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/views/database/DatabaseErrorView.kt @@ -44,7 +44,7 @@ fun DatabaseErrorView( fun callRunChat(confirmMigrations: MigrationConfirmation? = null) { val useKey = if (useKeychain) null else dbKey.value - runChat(useKey, confirmMigrations, chatDbStatus, progressIndicator, appPreferences) + runChat(useKey, confirmMigrations, chatDbStatus, progressIndicator) } fun saveAndRunChatOnClick() { @@ -190,13 +190,14 @@ private fun runChat( confirmMigrations: MigrationConfirmation? = null, chatDbStatus: State<DBMigrationResult?>, progressIndicator: MutableState<Boolean>, - prefs: AppPreferences ) = CoroutineScope(Dispatchers.Default).launch { // Don't do things concurrently. Shouldn't be here concurrently, just in case if (progressIndicator.value) return@launch progressIndicator.value = true try { - initChatController(dbKey, confirmMigrations) + initChatController(dbKey, confirmMigrations, + startChat = if (appPreferences.chatStopped.get()) ::showStartChatAfterRestartAlert else { { CompletableDeferred(true) } } + ) } catch (e: Exception) { Log.d(TAG, "initializeChat ${e.stackTraceToString()}") } diff --git a/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/views/database/DatabaseView.kt b/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/views/database/DatabaseView.kt index 2251d890fd..2d644b297e 100644 --- a/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/views/database/DatabaseView.kt +++ b/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/views/database/DatabaseView.kt @@ -27,6 +27,7 @@ import chat.simplex.common.views.helpers.* import chat.simplex.common.views.usersettings.* import chat.simplex.common.platform.* import chat.simplex.res.MR +import kotlinx.coroutines.delay import kotlinx.coroutines.sync.withLock import kotlinx.datetime.* import java.io.* @@ -88,8 +89,8 @@ fun DatabaseView( chatItemTTL, user, m.users, - startChat = { startChat(m, chatLastStart, m.chatDbChanged) }, - stopChatAlert = { stopChatAlert(m) }, + startChat = { startChat(m, chatLastStart, m.chatDbChanged, progressIndicator) }, + stopChatAlert = { stopChatAlert(m, progressIndicator) }, exportArchive = { exportArchive(m, progressIndicator, chatArchiveName, chatArchiveTime, chatArchiveFile, saveArchiveLauncher) }, deleteChatAlert = { deleteChatAlert(m, progressIndicator) }, deleteAppFilesAndMedia = { deleteFilesAndMediaAlert(appFilesCountAndSize) }, @@ -187,7 +188,7 @@ fun DatabaseLayout( Text(generalGetString(MR.strings.disconnect_remote_hosts), Modifier.fillMaxWidth(), color = WarningOrange) } } - RunChatSetting(runChat, stopped, toggleEnabled, startChat, stopChatAlert) + RunChatSetting(runChat, stopped, toggleEnabled && !progressIndicator, startChat, stopChatAlert) } SectionTextFooter( if (stopped) { @@ -239,7 +240,7 @@ fun DatabaseLayout( SettingsActionItem( painterResource(MR.images.ic_download), stringResource(MR.strings.import_database), - { withApi { importArchiveLauncher.launch("application/zip") } }, + { withLongRunningApi { importArchiveLauncher.launch("application/zip") } }, textColor = Color.Red, iconColor = Color.Red, disabled = operationsDisabled @@ -366,9 +367,10 @@ fun chatArchiveTitle(chatArchiveTime: Instant, chatLastStart: Instant): String { return stringResource(if (chatArchiveTime < chatLastStart) MR.strings.old_database_archive else MR.strings.new_database_archive) } -fun startChat(m: ChatModel, chatLastStart: MutableState<Instant?>, chatDbChanged: MutableState<Boolean>) { - withApi { +fun startChat(m: ChatModel, chatLastStart: MutableState<Instant?>, chatDbChanged: MutableState<Boolean>, progressIndicator: MutableState<Boolean>? = null) { + withLongRunningApi(slow = 30_000, deadlock = 60_000) { try { + progressIndicator?.value = true if (chatDbChanged.value) { initChatController() chatDbChanged.value = false @@ -376,14 +378,14 @@ fun startChat(m: ChatModel, chatLastStart: MutableState<Instant?>, chatDbChanged if (m.chatDbStatus.value !is DBMigrationResult.OK) { /** Hide current view and show [DatabaseErrorView] */ ModalManager.closeAllModalsEverywhere() - return@withApi + return@withLongRunningApi } - if (m.currentUser.value == null) { + val user = m.currentUser.value + if (user == null) { ModalManager.closeAllModalsEverywhere() - return@withApi + return@withLongRunningApi } else { - m.controller.apiStartChat() - m.chatRunning.value = true + m.controller.startChat(user) } val ts = Clock.System.now() m.controller.appPrefs.chatLastStart.set(ts) @@ -392,16 +394,18 @@ fun startChat(m: ChatModel, chatLastStart: MutableState<Instant?>, chatDbChanged } catch (e: Error) { m.chatRunning.value = false AlertManager.shared.showAlertMsg(generalGetString(MR.strings.error_starting_chat), e.toString()) + } finally { + progressIndicator?.value = false } } } -private fun stopChatAlert(m: ChatModel) { +private fun stopChatAlert(m: ChatModel, progressIndicator: MutableState<Boolean>? = null) { AlertManager.shared.showAlertDialog( title = generalGetString(MR.strings.stop_chat_question), text = generalGetString(MR.strings.stop_chat_to_export_import_or_delete_chat_database), confirmText = generalGetString(MR.strings.stop_chat_confirmation), - onConfirm = { authStopChat(m) }, + onConfirm = { authStopChat(m, progressIndicator = progressIndicator) }, onDismiss = { m.chatRunning.value = true } ) } @@ -415,7 +419,7 @@ private fun exportProhibitedAlert() { ) } -fun authStopChat(m: ChatModel, onStop: (() -> Unit)? = null) { +fun authStopChat(m: ChatModel, progressIndicator: MutableState<Boolean>? = null, onStop: (() -> Unit)? = null) { if (m.controller.appPrefs.performLA.get()) { authenticate( generalGetString(MR.strings.auth_stop_chat), @@ -423,10 +427,11 @@ fun authStopChat(m: ChatModel, onStop: (() -> Unit)? = null) { completed = { laResult -> when (laResult) { LAResult.Success, is LAResult.Unavailable -> { - stopChat(m, onStop) + stopChat(m, progressIndicator, onStop) } is LAResult.Error -> { m.chatRunning.value = true + laFailedAlert() } is LAResult.Failed -> { m.chatRunning.value = true @@ -435,19 +440,22 @@ fun authStopChat(m: ChatModel, onStop: (() -> Unit)? = null) { } ) } else { - stopChat(m, onStop) + stopChat(m, progressIndicator, onStop) } } -private fun stopChat(m: ChatModel, onStop: (() -> Unit)? = null) { - withApi { +private fun stopChat(m: ChatModel, progressIndicator: MutableState<Boolean>? = null, onStop: (() -> Unit)? = null) { + withBGApi { try { + progressIndicator?.value = true stopChatAsync(m) platform.androidChatStopped() onStop?.invoke() } catch (e: Error) { m.chatRunning.value = true AlertManager.shared.showAlertMsg(generalGetString(MR.strings.error_stopping_chat), e.toString()) + } finally { + progressIndicator?.value = false } } } @@ -455,12 +463,39 @@ private fun stopChat(m: ChatModel, onStop: (() -> Unit)? = null) { suspend fun stopChatAsync(m: ChatModel) { m.controller.apiStopChat() m.chatRunning.value = false + controller.appPrefs.chatStopped.set(true) } suspend fun deleteChatAsync(m: ChatModel) { m.controller.apiDeleteStorage() DatabaseUtils.ksDatabasePassword.remove() m.controller.appPrefs.storeDBPassphrase.set(true) + deleteChatDatabaseFilesAndState() +} + +fun deleteChatDatabaseFilesAndState() { + val chat = File(dataDir, chatDatabaseFileName) + val chatBak = File(dataDir, "$chatDatabaseFileName.bak") + val agent = File(dataDir, agentDatabaseFileName) + val agentBak = File(dataDir, "$agentDatabaseFileName.bak") + chat.delete() + chatBak.delete() + agent.delete() + agentBak.delete() + filesDir.deleteRecursively() + filesDir.mkdir() + remoteHostsDir.deleteRecursively() + tmpDir.deleteRecursively() + tmpDir.mkdir() + DatabaseUtils.ksDatabasePassword.remove() + controller.appPrefs.storeDBPassphrase.set(true) + controller.ctrl = null + + // Clear sensitive data on screen just in case ModalManager will fail to prevent hiding its modals while database encrypts itself + chatModel.chatId.value = null + chatModel.chatItems.clear() + chatModel.chats.clear() + chatModel.users.clear() } private fun exportArchive( @@ -472,7 +507,7 @@ private fun exportArchive( saveArchiveLauncher: FileChooserLauncher ) { progressIndicator.value = true - withApi { + withLongRunningApi { try { val archiveFile = exportChatArchive(m, chatArchiveName, chatArchiveTime, chatArchiveFile) chatArchiveFile.value = archiveFile @@ -546,7 +581,7 @@ private fun importArchive( progressIndicator.value = true val archivePath = saveArchiveFromURI(importedArchiveURI) if (archivePath != null) { - withApi { + withLongRunningApi(slow = 60_000, deadlock = 180_000) { try { m.controller.apiDeleteStorage() try { @@ -614,7 +649,7 @@ private fun deleteChatAlert(m: ChatModel, progressIndicator: MutableState<Boolea private fun deleteChat(m: ChatModel, progressIndicator: MutableState<Boolean>) { progressIndicator.value = true - withApi { + withBGApi { try { deleteChatAsync(m) operationEnded(m, progressIndicator) { @@ -637,7 +672,7 @@ private fun setCiTTL( ) { Log.d(TAG, "DatabaseView setChatItemTTL ${chatItemTTL.value.seconds ?: -1}") progressIndicator.value = true - withApi { + withBGApi { try { m.controller.setChatItemTTL(rhId, chatItemTTL.value) // Update model on success diff --git a/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/views/helpers/AlertManager.kt b/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/views/helpers/AlertManager.kt index 177efbfddc..082d733205 100644 --- a/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/views/helpers/AlertManager.kt +++ b/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/views/helpers/AlertManager.kt @@ -22,24 +22,27 @@ import chat.simplex.common.ui.theme.* import chat.simplex.res.MR import dev.icerock.moko.resources.StringResource import dev.icerock.moko.resources.compose.painterResource +import kotlinx.coroutines.flow.MutableStateFlow class AlertManager { - private var alertViews = mutableStateListOf<(@Composable () -> Unit)>() + // Don't use mutableStateOf() here, because it produces this if showing from SimpleXAPI.startChat(): + // java.lang.IllegalStateException: Reading a state that was created after the snapshot was taken or in a snapshot that has not yet been applied + private var alertViews = MutableStateFlow(listOf<(@Composable () -> Unit)>()) fun showAlert(alert: @Composable () -> Unit) { Log.d(TAG, "AlertManager.showAlert") - alertViews.add(alert) + alertViews.value += alert } fun hideAlert() { - alertViews.removeLastOrNull() + alertViews.value = ArrayList(alertViews.value).also { it.removeLastOrNull() } } fun hideAllAlerts() { - alertViews.clear() + alertViews.value = listOf() } - fun hasAlertsShown() = alertViews.isNotEmpty() + fun hasAlertsShown() = alertViews.value.isNotEmpty() fun showAlertDialogButtons( title: String, @@ -62,7 +65,28 @@ class AlertManager { fun showAlertDialogButtonsColumn( title: String, - text: AnnotatedString? = null, + text: String? = null, + onDismissRequest: (() -> Unit)? = null, + hostDevice: Pair<Long?, String>? = null, + buttons: @Composable () -> Unit, + ) { + showAlert { + AlertDialog( + onDismissRequest = { onDismissRequest?.invoke(); hideAlert() }, + title = alertTitle(title), + buttons = { + AlertContent(text, hostDevice, extraPadding = true) { + buttons() + } + }, + shape = RoundedCornerShape(corner = CornerSize(25.dp)) + ) + } + } + + fun showAlertDialogButtonsColumn( + title: String, + text: AnnotatedString, onDismissRequest: (() -> Unit)? = null, hostDevice: Pair<Long?, String>? = null, buttons: @Composable () -> Unit, @@ -221,7 +245,7 @@ class AlertManager { @Composable fun showInView() { - remember { alertViews }.lastOrNull()?.invoke() + alertViews.collectAsState().value.lastOrNull()?.invoke() } companion object { diff --git a/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/views/helpers/ChatInfoImage.kt b/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/views/helpers/ChatInfoImage.kt index abc894942f..6813bec550 100644 --- a/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/views/helpers/ChatInfoImage.kt +++ b/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/views/helpers/ChatInfoImage.kt @@ -17,6 +17,7 @@ import androidx.compose.ui.unit.Dp import androidx.compose.ui.unit.dp import chat.simplex.common.model.ChatInfo import chat.simplex.common.platform.base64ToBitmap +import chat.simplex.common.ui.theme.NoteFolderIconColor import chat.simplex.common.ui.theme.SimpleXTheme import chat.simplex.res.MR import dev.icerock.moko.resources.ImageResource @@ -24,9 +25,12 @@ import dev.icerock.moko.resources.ImageResource @Composable fun ChatInfoImage(chatInfo: ChatInfo, size: Dp, iconColor: Color = MaterialTheme.colors.secondaryVariant) { val icon = - if (chatInfo is ChatInfo.Group) MR.images.ic_supervised_user_circle_filled - else MR.images.ic_account_circle_filled - ProfileImage(size, chatInfo.image, icon, iconColor) + when (chatInfo) { + is ChatInfo.Group -> MR.images.ic_supervised_user_circle_filled + is ChatInfo.Local -> MR.images.ic_folder_filled + else -> MR.images.ic_account_circle_filled + } + ProfileImage(size, chatInfo.image, icon, if (chatInfo is ChatInfo.Local) NoteFolderIconColor else iconColor) } @Composable diff --git a/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/views/helpers/CustomTimePicker.kt b/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/views/helpers/CustomTimePicker.kt index fb1df940d9..f13edd618d 100644 --- a/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/views/helpers/CustomTimePicker.kt +++ b/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/views/helpers/CustomTimePicker.kt @@ -152,7 +152,8 @@ fun CustomTimePickerDialog( ) { DefaultDialog(onDismissRequest = cancel) { Surface( - shape = RoundedCornerShape(corner = CornerSize(25.dp)) + shape = RoundedCornerShape(corner = CornerSize(25.dp)), + contentColor = LocalContentColor.current ) { Box( contentAlignment = Alignment.Center diff --git a/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/views/helpers/DatabaseUtils.kt b/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/views/helpers/DatabaseUtils.kt index e7da47f8f0..52dc2c0658 100644 --- a/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/views/helpers/DatabaseUtils.kt +++ b/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/views/helpers/DatabaseUtils.kt @@ -75,14 +75,13 @@ object DatabaseUtils { sealed class DBMigrationResult { @Serializable @SerialName("ok") object OK: DBMigrationResult() @Serializable @SerialName("invalidConfirmation") object InvalidConfirmation: DBMigrationResult() - @Serializable @SerialName("errorNotADatabase") class ErrorNotADatabase(val dbFile: String): DBMigrationResult() - @Serializable @SerialName("errorMigration") class ErrorMigration(val dbFile: String, val migrationError: MigrationError): DBMigrationResult() - @Serializable @SerialName("errorSQL") class ErrorSQL(val dbFile: String, val migrationSQLError: String): DBMigrationResult() + @Serializable @SerialName("errorNotADatabase") data class ErrorNotADatabase(val dbFile: String): DBMigrationResult() + @Serializable @SerialName("errorMigration") data class ErrorMigration(val dbFile: String, val migrationError: MigrationError): DBMigrationResult() + @Serializable @SerialName("errorSQL") data class ErrorSQL(val dbFile: String, val migrationSQLError: String): DBMigrationResult() @Serializable @SerialName("errorKeychain") object ErrorKeychain: DBMigrationResult() - @Serializable @SerialName("unknown") class Unknown(val json: String): DBMigrationResult() + @Serializable @SerialName("unknown") data class Unknown(val json: String): DBMigrationResult() } - enum class MigrationConfirmation(val value: String) { YesUp("yesUp"), YesUpDown ("yesUpDown"), @@ -90,7 +89,7 @@ enum class MigrationConfirmation(val value: String) { } fun defaultMigrationConfirmation(appPrefs: AppPreferences): MigrationConfirmation = - if (appPrefs.confirmDBUpgrades.get()) MigrationConfirmation.Error else MigrationConfirmation.YesUp + if (appPrefs.developerTools.get() && appPrefs.confirmDBUpgrades.get()) MigrationConfirmation.Error else MigrationConfirmation.YesUp @Serializable sealed class MigrationError { diff --git a/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/views/helpers/DefaultProgressBar.kt b/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/views/helpers/DefaultProgressBar.kt new file mode 100644 index 0000000000..ec2500ab2e --- /dev/null +++ b/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/views/helpers/DefaultProgressBar.kt @@ -0,0 +1,27 @@ +package chat.simplex.common.views.helpers + +import androidx.compose.foundation.layout.* +import androidx.compose.material.* +import androidx.compose.runtime.Composable +import androidx.compose.ui.Alignment +import androidx.compose.ui.Modifier +import androidx.compose.ui.unit.dp +import chat.simplex.common.ui.theme.DEFAULT_PADDING + +@Composable +fun DefaultProgressView(description: String?) { + Box(Modifier.fillMaxSize(), contentAlignment = Alignment.Center) { + Column(horizontalAlignment = Alignment.CenterHorizontally) { + CircularProgressIndicator( + Modifier + .padding(bottom = DEFAULT_PADDING) + .size(30.dp), + color = MaterialTheme.colors.secondary, + strokeWidth = 2.5.dp + ) + if (description != null) { + Text(description) + } + } + } +} diff --git a/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/views/helpers/DefaultTopAppBar.kt b/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/views/helpers/DefaultTopAppBar.kt index 0162ac7e78..93be24d921 100644 --- a/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/views/helpers/DefaultTopAppBar.kt +++ b/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/views/helpers/DefaultTopAppBar.kt @@ -36,7 +36,7 @@ fun DefaultTopAppBar( SearchTextField(Modifier.fillMaxWidth(), alwaysVisible = false, onValueChange = onSearchValueChanged) } }, - backgroundColor = if (isInDarkTheme()) ToolbarDark else ToolbarLight, + backgroundColor = MaterialTheme.colors.background.mixWith(MaterialTheme.colors.onBackground, 0.97f), navigationIcon = navigationButton, buttons = if (!showSearch) buttons else emptyList(), centered = !showSearch, diff --git a/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/views/helpers/ExposedDropDownSettingRow.kt b/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/views/helpers/ExposedDropDownSettingRow.kt index 290bc2cd07..043aa5ec84 100644 --- a/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/views/helpers/ExposedDropDownSettingRow.kt +++ b/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/views/helpers/ExposedDropDownSettingRow.kt @@ -70,7 +70,7 @@ fun <T> ExposedDropDownSetting( selectionOption.second + (if (label != null) " $label" else ""), maxLines = 1, overflow = TextOverflow.Ellipsis, - color = if (isInDarkTheme()) MenuTextColorDark else Color.Black, + color = MenuTextColor, fontSize = fontSize, ) } diff --git a/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/views/helpers/LocalAuthentication.kt b/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/views/helpers/LocalAuthentication.kt index 8e6c9fffc1..022ee37589 100644 --- a/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/views/helpers/LocalAuthentication.kt +++ b/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/views/helpers/LocalAuthentication.kt @@ -1,8 +1,7 @@ package chat.simplex.common.views.helpers import androidx.compose.foundation.layout.fillMaxSize -import androidx.compose.material.MaterialTheme -import androidx.compose.material.Surface +import androidx.compose.material.* import androidx.compose.ui.Modifier import chat.simplex.common.model.ChatController import chat.simplex.common.model.ChatModel @@ -50,7 +49,7 @@ fun authenticateWithPasscode( close() completed(LAResult.Error(generalGetString(MR.strings.authentication_cancelled))) } - Surface(Modifier.fillMaxSize(), color = MaterialTheme.colors.background) { + Surface(Modifier.fillMaxSize(), color = MaterialTheme.colors.background, contentColor = LocalContentColor.current) { LocalAuthView(ChatModel, LocalAuthRequest(promptTitle, promptSubtitle, password, selfDestruct && ChatController.appPrefs.selfDestruct.get()) { close() completed(it) diff --git a/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/views/helpers/ModalView.kt b/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/views/helpers/ModalView.kt index 703b6f905f..f41d217646 100644 --- a/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/views/helpers/ModalView.kt +++ b/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/views/helpers/ModalView.kt @@ -11,6 +11,7 @@ import androidx.compose.ui.graphics.Color import chat.simplex.common.model.ChatModel import chat.simplex.common.platform.* import chat.simplex.common.ui.theme.* +import kotlinx.coroutines.flow.MutableStateFlow import java.util.concurrent.atomic.AtomicBoolean import kotlin.math.min @@ -26,7 +27,7 @@ fun ModalView( if (showClose) { BackHandler(onBack = close) } - Surface(Modifier.fillMaxSize()) { + Surface(Modifier.fillMaxSize(), contentColor = LocalContentColor.current) { Column(if (background != MaterialTheme.colors.background) Modifier.background(background) else Modifier.themedBackground()) { CloseSheetBar(close, showClose, endButtons) Box(modifier) { content() } @@ -38,27 +39,38 @@ enum class ModalPlacement { START, CENTER, END, FULLSCREEN } +class ModalData { + private val state = mutableMapOf<String, MutableState<Any>>() + fun <T> stateGetOrPut (key: String, default: () -> T): MutableState<T> = + state.getOrPut(key) { mutableStateOf(default() as Any) } as MutableState<T> +} + class ModalManager(private val placement: ModalPlacement? = null) { - private val modalViews = arrayListOf<Pair<Boolean, (@Composable (close: () -> Unit) -> Unit)>>() + private val modalViews = arrayListOf<Triple<Boolean, ModalData, (@Composable ModalData.(close: () -> Unit) -> Unit)>>() private val modalCount = mutableStateOf(0) private val toRemove = mutableSetOf<Int>() private var oldViewChanging = AtomicBoolean(false) - private var passcodeView: MutableState<(@Composable (close: () -> Unit) -> Unit)?> = mutableStateOf(null) + // Don't use mutableStateOf() here, because it produces this if showing from SimpleXAPI.startChat(): + // java.lang.IllegalStateException: Reading a state that was created after the snapshot was taken or in a snapshot that has not yet been applied + private var passcodeView: MutableStateFlow<(@Composable (close: () -> Unit) -> Unit)?> = MutableStateFlow(null) - fun showModal(settings: Boolean = false, showClose: Boolean = true, endButtons: @Composable RowScope.() -> Unit = {}, content: @Composable () -> Unit) { + fun showModal(settings: Boolean = false, showClose: Boolean = true, endButtons: @Composable RowScope.() -> Unit = {}, content: @Composable ModalData.() -> Unit) { + val data = ModalData() showCustomModal { close -> - ModalView(close, showClose = showClose, endButtons = endButtons, content = content) + ModalView(close, showClose = showClose, endButtons = endButtons, content = { data.content() }) } } - fun showModalCloseable(settings: Boolean = false, showClose: Boolean = true, content: @Composable (close: () -> Unit) -> Unit) { + fun showModalCloseable(settings: Boolean = false, showClose: Boolean = true, content: @Composable ModalData.(close: () -> Unit) -> Unit) { + val data = ModalData() showCustomModal { close -> - ModalView(close, showClose = showClose, content = { content(close) }) + ModalView(close, showClose = showClose, content = { data.content(close) }) } } - fun showCustomModal(animated: Boolean = true, modal: @Composable (close: () -> Unit) -> Unit) { + fun showCustomModal(animated: Boolean = true, modal: @Composable ModalData.(close: () -> Unit) -> Unit) { Log.d(TAG, "ModalManager.showCustomModal") + val data = ModalData() // Means, animation is in progress or not started yet. Do not wait until animation finishes, just remove all from screen. // This is useful when invoking close() and ShowCustomModal one after another without delay. Otherwise, screen will hold prev view if (toRemove.isNotEmpty()) { @@ -67,7 +79,7 @@ class ModalManager(private val placement: ModalPlacement? = null) { // Make animated appearance only on Android (everytime) and on Desktop (when it's on the start part of the screen or modals > 0) // to prevent unneeded animation on different situations val anim = if (appPlatform.isAndroid) animated else animated && (modalCount.value > 0 || placement == ModalPlacement.START) - modalViews.add(anim to modal) + modalViews.add(Triple(anim, data, modal)) modalCount.value = modalViews.size - toRemove.size if (placement == ModalPlacement.CENTER) { @@ -109,7 +121,7 @@ class ModalManager(private val placement: ModalPlacement? = null) { fun showInView() { // Without animation if (modalCount.value > 0 && modalViews.lastOrNull()?.first == false) { - modalViews.lastOrNull()?.second?.invoke(::closeModal) + modalViews.lastOrNull()?.let { it.third(it.second, ::closeModal) } return } AnimatedContent(targetState = modalCount.value, @@ -121,7 +133,7 @@ class ModalManager(private val placement: ModalPlacement? = null) { }.using(SizeTransform(clip = false)) } ) { - modalViews.getOrNull(it - 1)?.second?.invoke(::closeModal) + modalViews.getOrNull(it - 1)?.let { it.third(it.second, ::closeModal) } // This is needed because if we delete from modalViews immediately on request, animation will be bad if (toRemove.isNotEmpty() && it == modalCount.value && transition.currentState == EnterExitState.Visible && !transition.isRunning) { runAtomically { toRemove.removeIf { elem -> modalViews.removeAt(elem); true } } @@ -131,7 +143,7 @@ class ModalManager(private val placement: ModalPlacement? = null) { @Composable fun showPasscodeInView() { - remember { passcodeView }.value?.invoke { passcodeView.value = null } + passcodeView.collectAsState().value?.invoke { passcodeView.value = null } } /** diff --git a/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/views/helpers/ProcessedErrors.kt b/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/views/helpers/ProcessedErrors.kt index 4b44777a3a..b645cb1ee6 100644 --- a/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/views/helpers/ProcessedErrors.kt +++ b/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/views/helpers/ProcessedErrors.kt @@ -16,7 +16,7 @@ class ProcessedErrors <T: AgentErrorType>(val interval: Long) { fun newError(error: T, offerRestart: Boolean) { timer.cancel() - timer = withBGApi { + timer = withLongRunningApi(slow = 70_000, deadlock = 130_000) { val delayBeforeNext = (lastShownTimestamp + interval) - System.currentTimeMillis() if ((lastShownOfferRestart || !offerRestart) && delayBeforeNext >= 0) { delay(delayBeforeNext) @@ -43,9 +43,8 @@ class ProcessedErrors <T: AgentErrorType>(val interval: Long) { title = title, text = text, confirmText = generalGetString(MR.strings.restart_chat_button), - onConfirm = { - withApi { restartChatOrApp() } - }) + onConfirm = ::restartChatOrApp + ) } else { AlertManager.shared.showAlertMsg( title = title, diff --git a/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/views/helpers/SearchTextField.kt b/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/views/helpers/SearchTextField.kt index 4b6c70df44..ca451bd3a2 100644 --- a/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/views/helpers/SearchTextField.kt +++ b/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/views/helpers/SearchTextField.kt @@ -22,6 +22,7 @@ import dev.icerock.moko.resources.compose.stringResource import androidx.compose.ui.text.TextStyle import androidx.compose.ui.text.font.FontWeight import androidx.compose.ui.text.input.* +import androidx.compose.ui.text.style.TextOverflow import androidx.compose.ui.unit.dp import androidx.compose.ui.unit.sp import chat.simplex.res.MR @@ -34,6 +35,8 @@ fun SearchTextField( alwaysVisible: Boolean, searchText: MutableState<TextFieldValue> = rememberSaveable(stateSaver = TextFieldValue.Saver) { mutableStateOf(TextFieldValue("")) }, placeholder: String = stringResource(MR.strings.search_verb), + enabled: Boolean = true, + trailingContent: @Composable (() -> Unit)? = null, onValueChange: (String) -> Unit ) { val focusRequester = remember { FocusRequester() } @@ -54,12 +57,12 @@ fun SearchTextField( } } - val enabled = true val colors = TextFieldDefaults.textFieldColors( backgroundColor = Color.Unspecified, textColor = MaterialTheme.colors.onBackground, focusedIndicatorColor = Color.Unspecified, unfocusedIndicatorColor = Color.Unspecified, + disabledIndicatorColor = Color.Unspecified, ) val shape = MaterialTheme.shapes.small.copy(bottomEnd = ZeroCornerSize, bottomStart = ZeroCornerSize) val interactionSource = remember { MutableInteractionSource() } @@ -77,6 +80,7 @@ fun SearchTextField( searchText.value = it onValueChange(it.text) }, + enabled = rememberUpdatedState(enabled).value, cursorBrush = SolidColor(colors.cursorColor(false).value), visualTransformation = VisualTransformation.None, keyboardOptions = KeyboardOptions(imeAction = ImeAction.Search), @@ -92,7 +96,7 @@ fun SearchTextField( value = searchText.value.text, innerTextField = innerTextField, placeholder = { - Text(placeholder) + Text(placeholder, maxLines = 1, overflow = TextOverflow.Ellipsis) }, trailingIcon = if (searchText.value.text.isNotEmpty()) {{ IconButton({ @@ -105,7 +109,7 @@ fun SearchTextField( }) { Icon(painterResource(MR.images.ic_close), stringResource(MR.strings.icon_descr_close_button), tint = MaterialTheme.colors.primary,) } - }} else null, + }} else trailingContent, singleLine = true, enabled = enabled, interactionSource = interactionSource, diff --git a/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/views/helpers/Utils.kt b/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/views/helpers/Utils.kt index 9a81b9f9d7..33ee72841e 100644 --- a/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/views/helpers/Utils.kt +++ b/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/views/helpers/Utils.kt @@ -2,6 +2,7 @@ package chat.simplex.common.views.helpers import androidx.compose.runtime.* import androidx.compose.runtime.saveable.Saver +import androidx.compose.runtime.saveable.rememberSaveable import androidx.compose.ui.graphics.* import androidx.compose.ui.platform.* import androidx.compose.ui.text.* @@ -21,15 +22,69 @@ import java.net.URI import java.nio.file.Files import java.text.SimpleDateFormat import java.util.* +import java.util.concurrent.Executors import kotlin.math.* -fun withApi(action: suspend CoroutineScope.() -> Unit): Job = withScope(GlobalScope, action) +private val singleThreadDispatcher = Executors.newSingleThreadExecutor().asCoroutineDispatcher() -fun withScope(scope: CoroutineScope, action: suspend CoroutineScope.() -> Unit): Job = - scope.launch { withContext(Dispatchers.Main, action) } +fun withApi(action: suspend CoroutineScope.() -> Unit): Job = + Exception().let { + CoroutineScope(Dispatchers.Main).launch(block = { wrapWithLogging(action, it) }) + } fun withBGApi(action: suspend CoroutineScope.() -> Unit): Job = - CoroutineScope(Dispatchers.Default).launch(block = action) + Exception().let { + CoroutineScope(singleThreadDispatcher).launch(block = { wrapWithLogging(action, it) }) + } + +fun withLongRunningApi(slow: Long = Long.MAX_VALUE, deadlock: Long = Long.MAX_VALUE, action: suspend CoroutineScope.() -> Unit): Job = + Exception().let { + CoroutineScope(Dispatchers.Default).launch(block = { wrapWithLogging(action, it, slow = slow, deadlock = deadlock) }) + } + +private suspend fun wrapWithLogging(action: suspend CoroutineScope.() -> Unit, exception: java.lang.Exception, slow: Long = 10_000, deadlock: Long = 60_000) = coroutineScope { + val start = System.currentTimeMillis() + val job = launch { + delay(deadlock) + Log.e(TAG, "Possible deadlock of the thread, not finished after ${deadlock / 1000}s:\n${exception.stackTraceToString()}") + AlertManager.shared.showAlertMsg( + title = generalGetString(MR.strings.possible_deadlock_title), + text = generalGetString(MR.strings.possible_deadlock_desc).format(deadlock / 1000, exception.stackTraceToString()), + ) + } + action() + job.cancel() + if (appPreferences.developerTools.get() && appPreferences.showSlowApiCalls.get()) { + val end = System.currentTimeMillis() + if (end - start > slow) { + Log.e(TAG, "Possible problem with execution of the thread, took ${(end - start) / 1000}s:\n${exception.stackTraceToString()}") + AlertManager.shared.showAlertMsg( + title = generalGetString(MR.strings.possible_slow_function_title), + text = generalGetString(MR.strings.possible_slow_function_desc).format((end - start) / 1000, exception.stackTraceToString()), + ) + } + } +} + +@OptIn(InternalCoroutinesApi::class) +suspend fun interruptIfCancelled() = coroutineScope { + if (!isActive) { + Log.d(TAG, "Coroutine was cancelled and interrupted: ${Exception().stackTraceToString()}") + throw coroutineContext.job.getCancellationException() + } +} + +/** + * This coroutine helper makes possible to cancel coroutine scope when a user goes back but not when the user rotates a screen + * */ +@Composable +fun ModalData.CancellableOnGoneJob(key: String = rememberSaveable { UUID.randomUUID().toString() }): MutableState<Job> { + val job = remember { stateGetOrPut<Job>(key) { Job() } } + DisposableEffectOnGone { + job.value.cancel() + } + return job +} enum class KeyboardState { Opened, Closed @@ -60,6 +115,9 @@ fun annotatedStringResource(id: StringResource, vararg args: Any?): AnnotatedStr } } +@Composable +expect fun SetupClipboardListener() + // maximum image file size to be auto-accepted const val MAX_IMAGE_SIZE: Long = 261_120 // 255KB const val MAX_IMAGE_SIZE_AUTO_RCV: Long = MAX_IMAGE_SIZE * 2 @@ -72,6 +130,8 @@ const val MAX_FILE_SIZE_SMP: Long = 8000000 const val MAX_FILE_SIZE_XFTP: Long = 1_073_741_824 // 1GB +const val MAX_FILE_SIZE_LOCAL: Long = Long.MAX_VALUE + expect fun getAppFileUri(fileName: String): URI // https://developer.android.com/training/data-storage/shared/documents-files#bitmap @@ -105,13 +165,14 @@ fun getThemeFromUri(uri: URI, withAlertOnException: Boolean = true): ThemeOverri return null } -fun saveImage(uri: URI, encrypted: Boolean): CryptoFile? { +fun saveImage(uri: URI): CryptoFile? { val bitmap = getBitmapFromUri(uri) ?: return null - return saveImage(bitmap, encrypted) + return saveImage(bitmap) } -fun saveImage(image: ImageBitmap, encrypted: Boolean): CryptoFile? { +fun saveImage(image: ImageBitmap): CryptoFile? { return try { + val encrypted = chatController.appPrefs.privacyEncryptLocalFiles.get() val ext = if (image.hasAlpha()) "png" else "jpg" val dataResized = resizeImageToDataSize(image, ext == "png", maxDataSize = MAX_IMAGE_SIZE) val destFileName = generateNewFileName("IMG", ext, File(getAppFilePath(""))) @@ -150,8 +211,9 @@ fun desktopSaveImageInTmp(uri: URI): CryptoFile? { } } -fun saveAnimImage(uri: URI, encrypted: Boolean): CryptoFile? { +fun saveAnimImage(uri: URI): CryptoFile? { return try { + val encrypted = chatController.appPrefs.privacyEncryptLocalFiles.get() val filename = getFileName(uri)?.lowercase() var ext = when { // remove everything but extension @@ -177,8 +239,9 @@ fun saveAnimImage(uri: URI, encrypted: Boolean): CryptoFile? { expect suspend fun saveTempImageUncompressed(image: ImageBitmap, asPng: Boolean): File? -fun saveFileFromUri(uri: URI, encrypted: Boolean, withAlertOnException: Boolean = true): CryptoFile? { +fun saveFileFromUri(uri: URI, withAlertOnException: Boolean = true): CryptoFile? { return try { + val encrypted = chatController.appPrefs.privacyEncryptLocalFiles.get() val inputStream = uri.inputStream() val fileToSave = getFileName(uri) return if (inputStream != null && fileToSave != null) { @@ -294,6 +357,7 @@ fun getMaxFileSize(fileProtocol: FileProtocol): Long { return when (fileProtocol) { FileProtocol.XFTP -> MAX_FILE_SIZE_XFTP FileProtocol.SMP -> MAX_FILE_SIZE_SMP + FileProtocol.LOCAL -> MAX_FILE_SIZE_LOCAL } } @@ -419,8 +483,12 @@ fun DisposableEffectOnGone(always: () -> Unit = {}, whenDispose: () -> Unit = {} val orientation = windowOrientation() onDispose { whenDispose() - if (orientation == windowOrientation()) { - whenGone() + withApi { + // It needs some delay before check orientation again because it can still be not updated to actual value + delay(300) + if (orientation == windowOrientation()) { + whenGone() + } } } } diff --git a/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/views/localauth/LocalAuthView.kt b/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/views/localauth/LocalAuthView.kt index 468dd8580e..1048b03bc0 100644 --- a/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/views/localauth/LocalAuthView.kt +++ b/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/views/localauth/LocalAuthView.kt @@ -1,32 +1,45 @@ package chat.simplex.common.views.localauth -import androidx.compose.runtime.Composable -import androidx.compose.runtime.mutableStateOf +import androidx.compose.runtime.* import androidx.compose.runtime.saveable.rememberSaveable +import chat.simplex.common.model.* +import chat.simplex.common.model.ChatModel.controller import dev.icerock.moko.resources.compose.stringResource -import chat.simplex.common.views.database.deleteChatAsync -import chat.simplex.common.views.database.stopChatAsync import chat.simplex.common.views.helpers.* import chat.simplex.common.views.helpers.DatabaseUtils.ksSelfDestructPassword import chat.simplex.common.views.helpers.DatabaseUtils.ksAppPassword import chat.simplex.common.views.onboarding.OnboardingStage -import chat.simplex.common.model.ChatModel -import chat.simplex.common.model.Profile import chat.simplex.common.platform.* +import chat.simplex.common.views.database.* import chat.simplex.res.MR +import kotlinx.coroutines.delay @Composable fun LocalAuthView(m: ChatModel, authRequest: LocalAuthRequest) { val passcode = rememberSaveable { mutableStateOf("") } - PasscodeView(passcode, authRequest.title ?: stringResource(MR.strings.la_enter_app_passcode), authRequest.reason, stringResource(MR.strings.submit_passcode), + val allowToReact = rememberSaveable { mutableStateOf(true) } + if (!allowToReact.value) { + BackHandler { + // do nothing until submit action finishes to prevent concurrent removing of storage + } + } + PasscodeView(passcode, authRequest.title ?: stringResource(MR.strings.la_enter_app_passcode), authRequest.reason, stringResource(MR.strings.submit_passcode), buttonsEnabled = allowToReact, submit = { val sdPassword = ksSelfDestructPassword.get() if (sdPassword == passcode.value && authRequest.selfDestruct) { + allowToReact.value = false deleteStorageAndRestart(m, sdPassword) { r -> authRequest.completed(r) } } else { - val r: LAResult = if (passcode.value == authRequest.password) LAResult.Success else LAResult.Error(generalGetString(MR.strings.incorrect_passcode)) + val r: LAResult = if (passcode.value == authRequest.password) { + if (authRequest.selfDestruct && sdPassword != null && controller.ctrl == -1L) { + initChatControllerAndRunMigrations() + } + LAResult.Success + } else { + LAResult.Error(generalGetString(MR.strings.incorrect_passcode)) + } authRequest.completed(r) } }, @@ -36,10 +49,25 @@ fun LocalAuthView(m: ChatModel, authRequest: LocalAuthRequest) { } private fun deleteStorageAndRestart(m: ChatModel, password: String, completed: (LAResult) -> Unit) { - withBGApi { + withLongRunningApi(slow = 30_000, deadlock = 60_000) { try { - stopChatAsync(m) - deleteChatAsync(m) + /** Waiting until [initChatController] finishes */ + while (m.ctrlInitInProgress.value) { + delay(50) + } + if (m.chatRunning.value == true) { + stopChatAsync(m) + } + val ctrl = m.controller.ctrl + if (ctrl != null && ctrl != -1L) { + /** + * The following sequence can bring a user here: + * the user opened the app, entered app passcode, went to background, returned back, entered self-destruct code. + * In this case database should be closed to prevent possible situation when OS can deny database removal command + * */ + chatCloseStore(ctrl) + } + deleteChatDatabaseFilesAndState() ksAppPassword.set(password) ksSelfDestructPassword.remove() ntfManager.cancelAllNotifications() @@ -48,16 +76,9 @@ private fun deleteStorageAndRestart(m: ChatModel, password: String, completed: ( val displayName = displayNamePref.get() selfDestructPref.set(false) displayNamePref.set(null) - m.chatDbChanged.value = true - m.chatDbStatus.value = null - try { - initChatController(startChat = true) - } catch (e: Exception) { - Log.d(TAG, "initializeChat ${e.stackTraceToString()}") - } - m.chatDbChanged.value = false + reinitChatController() if (m.currentUser.value != null) { - return@withBGApi + return@withLongRunningApi } var profile: Profile? = null if (!displayName.isNullOrEmpty()) { @@ -69,12 +90,24 @@ private fun deleteStorageAndRestart(m: ChatModel, password: String, completed: ( if (createdUser != null) { m.controller.startChat(createdUser) } - ModalManager.fullscreen.closeModals() + ModalManager.closeAllModalsEverywhere() AlertManager.shared.hideAllAlerts() AlertManager.privacySensitive.hideAllAlerts() completed(LAResult.Success) } catch (e: Exception) { + Log.e(TAG, "Unable to delete storage: ${e.stackTraceToString()}") completed(LAResult.Error(generalGetString(MR.strings.incorrect_passcode))) } } } + +suspend fun reinitChatController() { + chatModel.chatDbChanged.value = true + chatModel.chatDbStatus.value = null + try { + initChatController() + } catch (e: Exception) { + Log.d(TAG, "initializeChat ${e.stackTraceToString()}") + } + chatModel.chatDbChanged.value = false +} diff --git a/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/views/localauth/PasscodeView.kt b/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/views/localauth/PasscodeView.kt index 4784951ad0..2b2f006d25 100644 --- a/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/views/localauth/PasscodeView.kt +++ b/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/views/localauth/PasscodeView.kt @@ -12,6 +12,7 @@ import dev.icerock.moko.resources.compose.painterResource import androidx.compose.ui.unit.dp import chat.simplex.common.platform.* import chat.simplex.common.ui.theme.DEFAULT_PADDING +import chat.simplex.common.views.chat.group.ProgressIndicator import chat.simplex.common.views.helpers.SimpleButton import chat.simplex.common.views.helpers.* import chat.simplex.res.MR @@ -23,6 +24,7 @@ fun PasscodeView( reason: String? = null, submitLabel: String, submitEnabled: ((String) -> Boolean)? = null, + buttonsEnabled: State<Boolean> = remember { mutableStateOf(true) }, submit: () -> Unit, cancel: () -> Unit, ) { @@ -74,9 +76,9 @@ fun PasscodeView( } PasscodeEntry(passcode, true) Row(Modifier.heightIn(min = 70.dp), verticalAlignment = Alignment.CenterVertically) { - SimpleButton(generalGetString(MR.strings.cancel_verb), icon = painterResource(MR.images.ic_close), click = cancel) + SimpleButton(generalGetString(MR.strings.cancel_verb), icon = painterResource(MR.images.ic_close), disabled = !buttonsEnabled.value, click = cancel) Spacer(Modifier.size(20.dp)) - SimpleButton(submitLabel, icon = painterResource(MR.images.ic_done_filled), disabled = submitEnabled?.invoke(passcode.value) == false || passcode.value.length < 4, click = submit) + SimpleButton(submitLabel, icon = painterResource(MR.images.ic_done_filled), disabled = submitEnabled?.invoke(passcode.value) == false || passcode.value.length < 4 || !buttonsEnabled.value, click = submit) } } } @@ -117,8 +119,8 @@ fun PasscodeView( Modifier.padding(start = 30.dp).height(s * 3), verticalArrangement = Arrangement.SpaceEvenly ) { - SimpleButton(generalGetString(MR.strings.cancel_verb), icon = painterResource(MR.images.ic_close), click = cancel) - SimpleButton(submitLabel, icon = painterResource(MR.images.ic_done_filled), disabled = submitEnabled?.invoke(passcode.value) == false || passcode.value.length < 4, click = submit) + SimpleButton(generalGetString(MR.strings.cancel_verb), icon = painterResource(MR.images.ic_close), disabled = !buttonsEnabled.value, click = cancel) + SimpleButton(submitLabel, icon = painterResource(MR.images.ic_done_filled), disabled = submitEnabled?.invoke(passcode.value) == false || passcode.value.length < 4 || !buttonsEnabled.value, click = submit) } } } @@ -130,6 +132,9 @@ fun PasscodeView( } else { HorizontalLayout() } + if (!buttonsEnabled.value) { + ProgressIndicator() + } LaunchedEffect(Unit) { focusRequester.requestFocus() // Disallow to steal a focus by clicking on buttons or using Tab diff --git a/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/views/localauth/SetAppPasscodeView.kt b/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/views/localauth/SetAppPasscodeView.kt index 18437dbf98..1d620c915f 100644 --- a/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/views/localauth/SetAppPasscodeView.kt +++ b/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/views/localauth/SetAppPasscodeView.kt @@ -5,12 +5,14 @@ import androidx.compose.runtime.saveable.rememberSaveable import chat.simplex.common.platform.BackHandler import chat.simplex.common.views.helpers.DatabaseUtils import chat.simplex.common.views.helpers.DatabaseUtils.ksAppPassword +import chat.simplex.common.views.helpers.DatabaseUtils.ksSelfDestructPassword import chat.simplex.common.views.helpers.generalGetString import chat.simplex.res.MR @Composable fun SetAppPasscodeView( passcodeKeychain: DatabaseUtils.KeyStoreItem = ksAppPassword, + prohibitedPasscodeKeychain: DatabaseUtils.KeyStoreItem = ksSelfDestructPassword, title: String = generalGetString(MR.strings.new_passcode), reason: String? = null, submit: () -> Unit, @@ -48,7 +50,9 @@ fun SetAppPasscodeView( } } } else { - SetPasswordView(title, generalGetString(MR.strings.save_verb)) { + SetPasswordView(title, generalGetString(MR.strings.save_verb), + // Do not allow to set app passcode == selfDestruct passcode + submitEnabled = { pwd -> pwd != prohibitedPasscodeKeychain.get() }) { enteredPassword = passcode.value passcode.value = "" confirming = true diff --git a/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/views/newchat/AddContactLearnMore.kt b/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/views/newchat/AddContactLearnMore.kt index 2913f6ac79..c2523c9b2e 100644 --- a/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/views/newchat/AddContactLearnMore.kt +++ b/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/views/newchat/AddContactLearnMore.kt @@ -4,14 +4,16 @@ import androidx.compose.foundation.* import androidx.compose.foundation.layout.Column import androidx.compose.runtime.Composable import androidx.compose.ui.Modifier +import chat.simplex.common.platform.chatModel import dev.icerock.moko.resources.compose.stringResource import chat.simplex.common.views.helpers.AppBarTitle +import chat.simplex.common.views.helpers.KeyChangeEffect import chat.simplex.common.views.onboarding.ReadableText import chat.simplex.common.views.onboarding.ReadableTextWithLink import chat.simplex.res.MR @Composable -fun AddContactLearnMore() { +fun AddContactLearnMore(close: () -> Unit) { Column( Modifier.verticalScroll(rememberScrollState()), ) { @@ -20,4 +22,7 @@ fun AddContactLearnMore() { ReadableText(MR.strings.if_you_cant_meet_in_person) ReadableTextWithLink(MR.strings.read_more_in_user_guide_with_link, "https://simplex.chat/docs/guide/readme.html#connect-to-friends") } + KeyChangeEffect(chatModel.chatId.value) { + close() + } } diff --git a/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/views/newchat/AddContactView.kt b/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/views/newchat/AddContactView.kt deleted file mode 100644 index 84080d5b97..0000000000 --- a/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/views/newchat/AddContactView.kt +++ /dev/null @@ -1,186 +0,0 @@ -package chat.simplex.common.views.newchat - -import SectionBottomSpacer -import SectionTextFooter -import SectionView -import androidx.compose.desktop.ui.tooling.preview.Preview -import androidx.compose.foundation.layout.* -import androidx.compose.foundation.rememberScrollState -import androidx.compose.foundation.verticalScroll -import androidx.compose.material.* -import dev.icerock.moko.resources.compose.painterResource -import androidx.compose.runtime.* -import androidx.compose.ui.Alignment -import androidx.compose.ui.Modifier -import androidx.compose.ui.platform.LocalClipboardManager -import dev.icerock.moko.resources.compose.stringResource -import androidx.compose.ui.unit.dp -import chat.simplex.common.model.* -import chat.simplex.common.platform.shareText -import chat.simplex.common.ui.theme.* -import chat.simplex.common.views.helpers.* -import chat.simplex.common.views.usersettings.* -import chat.simplex.res.MR - -@Composable -fun AddContactView( - chatModel: ChatModel, - rh: RemoteHostInfo?, - connReqInvitation: String, - contactConnection: MutableState<PendingContactConnection?> -) { - val clipboard = LocalClipboardManager.current - AddContactLayout( - rh = rh, - chatModel = chatModel, - incognitoPref = chatModel.controller.appPrefs.incognito, - connReq = connReqInvitation, - contactConnection = contactConnection, - learnMore = { - ModalManager.center.showModal { - Column( - Modifier - .fillMaxHeight() - .padding(horizontal = DEFAULT_PADDING), - verticalArrangement = Arrangement.SpaceBetween - ) { - AddContactLearnMore() - } - } - } - ) -} - -@Composable -fun AddContactLayout( - chatModel: ChatModel, - rh: RemoteHostInfo?, - incognitoPref: SharedPreference<Boolean>, - connReq: String, - contactConnection: MutableState<PendingContactConnection?>, - learnMore: () -> Unit -) { - val incognito = remember { mutableStateOf(incognitoPref.get()) } - - LaunchedEffect(incognito.value) { - withApi { - val contactConnVal = contactConnection.value - if (contactConnVal != null) { - chatModel.controller.apiSetConnectionIncognito(rh?.remoteHostId, contactConnVal.pccConnId, incognito.value)?.let { - contactConnection.value = it - chatModel.updateContactConnection(rh?.remoteHostId, it) - } - } - } - } - - Column( - Modifier - .verticalScroll(rememberScrollState()), - verticalArrangement = Arrangement.SpaceBetween, - ) { - AppBarTitle(stringResource(MR.strings.add_contact), hostDevice(rh?.remoteHostId)) - - SectionView(stringResource(MR.strings.one_time_link_short).uppercase()) { - if (connReq.isNotEmpty()) { - SimpleXLinkQRCode( - connReq, Modifier - .padding(horizontal = DEFAULT_PADDING, vertical = DEFAULT_PADDING_HALF) - .aspectRatio(1f) - ) - } else { - CircularProgressIndicator( - Modifier - .size(36.dp) - .padding(4.dp) - .align(Alignment.CenterHorizontally), - color = MaterialTheme.colors.secondary, - strokeWidth = 3.dp - ) - } - - IncognitoToggle(incognitoPref, incognito) { ModalManager.start.showModal { IncognitoView() } } - ShareLinkButton(connReq) - OneTimeLinkLearnMoreButton(learnMore) - } - SectionTextFooter(sharedProfileInfo(chatModel, incognito.value)) - - SectionBottomSpacer() - } -} - -@Composable -fun ShareLinkButton(connReqInvitation: String) { - val clipboard = LocalClipboardManager.current - SettingsActionItem( - painterResource(MR.images.ic_share), - stringResource(MR.strings.share_invitation_link), - click = { clipboard.shareText(simplexChatLink(connReqInvitation)) }, - iconColor = MaterialTheme.colors.primary, - textColor = MaterialTheme.colors.primary, - ) -} - -@Composable -fun OneTimeLinkLearnMoreButton(onClick: () -> Unit) { - SettingsActionItem( - painterResource(MR.images.ic_info), - stringResource(MR.strings.learn_more), - onClick, - ) -} - -@Composable -fun IncognitoToggle( - incognitoPref: SharedPreference<Boolean>, - incognito: MutableState<Boolean>, - onClickInfo: () -> Unit -) { - SettingsActionItemWithContent( - icon = if (incognito.value) painterResource(MR.images.ic_theater_comedy_filled) else painterResource(MR.images.ic_theater_comedy), - text = null, - click = onClickInfo, - iconColor = if (incognito.value) Indigo else MaterialTheme.colors.secondary, - extraPadding = false - ) { - SharedPreferenceToggleWithIcon( - stringResource(MR.strings.incognito), - painterResource(MR.images.ic_info), - stopped = false, - onClickInfo = onClickInfo, - preference = incognitoPref, - preferenceState = incognito - ) - } -} - -fun sharedProfileInfo( - chatModel: ChatModel, - incognito: Boolean -): String { - val name = chatModel.currentUser.value?.displayName ?: "" - return if (incognito) { - generalGetString(MR.strings.connect__a_new_random_profile_will_be_shared) - } else { - String.format(generalGetString(MR.strings.connect__your_profile_will_be_shared), name) - } -} - -@Preview/*( - uiMode = Configuration.UI_MODE_NIGHT_YES, - showBackground = true, - name = "Dark Mode" -)*/ -@Composable -fun PreviewAddContactView() { - SimpleXTheme { - AddContactLayout( - rh = null, - chatModel = ChatModel, - incognitoPref = SharedPreference({ false }, {}), - connReq = "https://simplex.chat/contact#/?v=1&smp=smp%3A%2F%2FPQUV2eL0t7OStZOoAsPEV2QYWt4-xilbakvGUGOItUo%3D%40smp6.simplex.im%2FK1rslx-m5bpXVIdMZg9NLUZ_8JBm8xTt%23MCowBQYDK2VuAyEALDeVe-sG8mRY22LsXlPgiwTNs9dbiLrNuA7f3ZMAJ2w%3D", - contactConnection = mutableStateOf(PendingContactConnection.getSampleData()), - learnMore = {}, - ) - } -} diff --git a/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/views/newchat/AddGroupView.kt b/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/views/newchat/AddGroupView.kt index 4f71e81b0d..ee03028909 100644 --- a/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/views/newchat/AddGroupView.kt +++ b/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/views/newchat/AddGroupView.kt @@ -36,7 +36,7 @@ fun AddGroupView(chatModel: ChatModel, rh: RemoteHostInfo?, close: () -> Unit) { val rhId = rh?.remoteHostId AddGroupLayout( createGroup = { incognito, groupProfile -> - withApi { + withBGApi { val groupInfo = chatModel.controller.apiNewGroup(rhId, incognito, groupProfile) if (groupInfo != null) { chatModel.addChat(Chat(remoteHostId = rhId, chatInfo = ChatInfo.Group(groupInfo), chatItems = listOf())) @@ -139,7 +139,8 @@ fun AddGroupLayout( createGroup(incognito.value, GroupProfile( displayName = displayName.value.trim(), fullName = "", - image = profileImage.value + image = profileImage.value, + groupPreferences = GroupPreferences(history = GroupPreference(GroupFeatureEnabled.ON)) )) }, textColor = MaterialTheme.colors.primary, diff --git a/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/views/newchat/ScanToConnectView.kt b/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/views/newchat/ConnectPlan.kt similarity index 69% rename from apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/views/newchat/ScanToConnectView.kt rename to apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/views/newchat/ConnectPlan.kt index 9f28074aef..5b56fe5e39 100644 --- a/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/views/newchat/ScanToConnectView.kt +++ b/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/views/newchat/ConnectPlan.kt @@ -1,57 +1,51 @@ package chat.simplex.common.views.newchat -import SectionBottomSpacer import SectionItemView -import SectionTextFooter -import androidx.compose.desktop.ui.tooling.preview.Preview import androidx.compose.foundation.layout.* -import androidx.compose.foundation.rememberScrollState -import androidx.compose.foundation.verticalScroll import androidx.compose.material.* -import androidx.compose.runtime.* import androidx.compose.ui.Modifier -import androidx.compose.ui.text.AnnotatedString -import androidx.compose.ui.text.buildAnnotatedString import androidx.compose.ui.text.style.TextAlign import dev.icerock.moko.resources.compose.stringResource -import androidx.compose.ui.unit.dp import chat.simplex.common.model.* import chat.simplex.common.platform.* -import chat.simplex.common.ui.theme.* import chat.simplex.common.views.chatlist.* import chat.simplex.common.views.helpers.* -import chat.simplex.common.views.usersettings.IncognitoView import chat.simplex.res.MR import java.net.URI -@Composable -expect fun ScanToConnectView(chatModel: ChatModel, rh: RemoteHostInfo?, close: () -> Unit) - enum class ConnectionLinkType { INVITATION, CONTACT, GROUP } suspend fun planAndConnect( - chatModel: ChatModel, rhId: Long?, uri: URI, incognito: Boolean?, - close: (() -> Unit)? + close: (() -> Unit)?, + cleanup: (() -> Unit)? = null, + filterKnownContact: ((Contact) -> Unit)? = null, + filterKnownGroup: ((GroupInfo) -> Unit)? = null, ) { val connectionPlan = chatModel.controller.apiConnectPlan(rhId, uri.toString()) if (connectionPlan != null) { + val link = strHasSingleSimplexLink(uri.toString().trim()) + val linkText = if (link?.format is Format.SimplexLink) + "<br><br><u>${link.simplexLinkText(link.format.linkType, link.format.smpHosts)}</u>" + else + "" when (connectionPlan) { is ConnectionPlan.InvitationLink -> when (connectionPlan.invitationLinkPlan) { InvitationLinkPlan.Ok -> { Log.d(TAG, "planAndConnect, .InvitationLink, .Ok, incognito=$incognito") if (incognito != null) { - connectViaUri(chatModel, rhId, uri, incognito, connectionPlan, close) + connectViaUri(chatModel, rhId, uri, incognito, connectionPlan, close, cleanup) } else { askCurrentOrIncognitoProfileAlert( chatModel, rhId, uri, connectionPlan, close, title = generalGetString(MR.strings.connect_via_invitation_link), - text = AnnotatedString(generalGetString(MR.strings.profile_will_be_sent_to_contact_sending_link)), - connectDestructive = false + text = generalGetString(MR.strings.profile_will_be_sent_to_contact_sending_link) + linkText, + connectDestructive = false, + cleanup = cleanup, ) } } @@ -60,9 +54,11 @@ suspend fun planAndConnect( if (incognito != null) { AlertManager.privacySensitive.showAlertDialog( title = generalGetString(MR.strings.connect_plan_connect_to_yourself), - text = generalGetString(MR.strings.connect_plan_this_is_your_own_one_time_link), + text = generalGetString(MR.strings.connect_plan_this_is_your_own_one_time_link) + linkText, confirmText = if (incognito) generalGetString(MR.strings.connect_via_link_incognito) else generalGetString(MR.strings.connect_via_link_verb), - onConfirm = { withApi { connectViaUri(chatModel, rhId, uri, incognito, connectionPlan, close) } }, + onConfirm = { withBGApi { connectViaUri(chatModel, rhId, uri, incognito, connectionPlan, close, cleanup) } }, + onDismiss = cleanup, + onDismissRequest = cleanup, destructive = true, hostDevice = hostDevice(rhId), ) @@ -70,8 +66,9 @@ suspend fun planAndConnect( askCurrentOrIncognitoProfileAlert( chatModel, rhId, uri, connectionPlan, close, title = generalGetString(MR.strings.connect_plan_connect_to_yourself), - text = AnnotatedString(generalGetString(MR.strings.connect_plan_this_is_your_own_one_time_link)), - connectDestructive = true + text = generalGetString(MR.strings.connect_plan_this_is_your_own_one_time_link) + linkText, + connectDestructive = true, + cleanup = cleanup, ) } } @@ -79,42 +76,54 @@ suspend fun planAndConnect( Log.d(TAG, "planAndConnect, .InvitationLink, .Connecting, incognito=$incognito") val contact = connectionPlan.invitationLinkPlan.contact_ if (contact != null) { - openKnownContact(chatModel, rhId, close, contact) - AlertManager.privacySensitive.showAlertMsg( - generalGetString(MR.strings.contact_already_exists), - String.format(generalGetString(MR.strings.connect_plan_you_are_already_connecting_to_vName), contact.displayName), - hostDevice = hostDevice(rhId), - ) + if (filterKnownContact != null) { + filterKnownContact(contact) + } else { + openKnownContact(chatModel, rhId, close, contact) + AlertManager.privacySensitive.showAlertMsg( + generalGetString(MR.strings.contact_already_exists), + String.format(generalGetString(MR.strings.connect_plan_you_are_already_connecting_to_vName), contact.displayName) + linkText, + hostDevice = hostDevice(rhId), + ) + cleanup?.invoke() + } } else { AlertManager.privacySensitive.showAlertMsg( generalGetString(MR.strings.connect_plan_already_connecting), - generalGetString(MR.strings.connect_plan_you_are_already_connecting_via_this_one_time_link), + generalGetString(MR.strings.connect_plan_you_are_already_connecting_via_this_one_time_link) + linkText, hostDevice = hostDevice(rhId), ) + cleanup?.invoke() } } is InvitationLinkPlan.Known -> { Log.d(TAG, "planAndConnect, .InvitationLink, .Known, incognito=$incognito") val contact = connectionPlan.invitationLinkPlan.contact - openKnownContact(chatModel, rhId, close, contact) - AlertManager.privacySensitive.showAlertMsg( - generalGetString(MR.strings.contact_already_exists), - String.format(generalGetString(MR.strings.you_are_already_connected_to_vName_via_this_link), contact.displayName), - hostDevice = hostDevice(rhId), - ) + if (filterKnownContact != null) { + filterKnownContact(contact) + } else { + openKnownContact(chatModel, rhId, close, contact) + AlertManager.privacySensitive.showAlertMsg( + generalGetString(MR.strings.contact_already_exists), + String.format(generalGetString(MR.strings.you_are_already_connected_to_vName_via_this_link), contact.displayName) + linkText, + hostDevice = hostDevice(rhId), + ) + cleanup?.invoke() + } } } is ConnectionPlan.ContactAddress -> when (connectionPlan.contactAddressPlan) { ContactAddressPlan.Ok -> { Log.d(TAG, "planAndConnect, .ContactAddress, .Ok, incognito=$incognito") if (incognito != null) { - connectViaUri(chatModel, rhId, uri, incognito, connectionPlan, close) + connectViaUri(chatModel, rhId, uri, incognito, connectionPlan, close, cleanup) } else { askCurrentOrIncognitoProfileAlert( chatModel, rhId, uri, connectionPlan, close, title = generalGetString(MR.strings.connect_via_contact_link), - text = AnnotatedString(generalGetString(MR.strings.profile_will_be_sent_to_contact_sending_link)), - connectDestructive = false + text = generalGetString(MR.strings.profile_will_be_sent_to_contact_sending_link) + linkText, + connectDestructive = false, + cleanup, ) } } @@ -123,18 +132,21 @@ suspend fun planAndConnect( if (incognito != null) { AlertManager.privacySensitive.showAlertDialog( title = generalGetString(MR.strings.connect_plan_connect_to_yourself), - text = generalGetString(MR.strings.connect_plan_this_is_your_own_simplex_address), + text = generalGetString(MR.strings.connect_plan_this_is_your_own_simplex_address) + linkText, confirmText = if (incognito) generalGetString(MR.strings.connect_via_link_incognito) else generalGetString(MR.strings.connect_via_link_verb), - onConfirm = { withApi { connectViaUri(chatModel, rhId, uri, incognito, connectionPlan, close) } }, + onConfirm = { withBGApi { connectViaUri(chatModel, rhId, uri, incognito, connectionPlan, close, cleanup) } }, destructive = true, + onDismiss = cleanup, + onDismissRequest = cleanup, hostDevice = hostDevice(rhId), ) } else { askCurrentOrIncognitoProfileAlert( chatModel, rhId, uri, connectionPlan, close, title = generalGetString(MR.strings.connect_plan_connect_to_yourself), - text = AnnotatedString(generalGetString(MR.strings.connect_plan_this_is_your_own_simplex_address)), - connectDestructive = true + text = generalGetString(MR.strings.connect_plan_this_is_your_own_simplex_address) + linkText, + connectDestructive = true, + cleanup = cleanup, ) } } @@ -143,9 +155,11 @@ suspend fun planAndConnect( if (incognito != null) { AlertManager.privacySensitive.showAlertDialog( title = generalGetString(MR.strings.connect_plan_repeat_connection_request), - text = generalGetString(MR.strings.connect_plan_you_have_already_requested_connection_via_this_address), + text = generalGetString(MR.strings.connect_plan_you_have_already_requested_connection_via_this_address) + linkText, confirmText = if (incognito) generalGetString(MR.strings.connect_via_link_incognito) else generalGetString(MR.strings.connect_via_link_verb), - onConfirm = { withApi { connectViaUri(chatModel, rhId, uri, incognito, connectionPlan, close) } }, + onConfirm = { withBGApi { connectViaUri(chatModel, rhId, uri, incognito, connectionPlan, close, cleanup) } }, + onDismiss = cleanup, + onDismissRequest = cleanup, destructive = true, hostDevice = hostDevice(rhId), ) @@ -153,30 +167,41 @@ suspend fun planAndConnect( askCurrentOrIncognitoProfileAlert( chatModel, rhId, uri, connectionPlan, close, title = generalGetString(MR.strings.connect_plan_repeat_connection_request), - text = AnnotatedString(generalGetString(MR.strings.connect_plan_you_have_already_requested_connection_via_this_address)), - connectDestructive = true + text = generalGetString(MR.strings.connect_plan_you_have_already_requested_connection_via_this_address) + linkText, + connectDestructive = true, + cleanup = cleanup, ) } } is ContactAddressPlan.ConnectingProhibit -> { Log.d(TAG, "planAndConnect, .ContactAddress, .ConnectingProhibit, incognito=$incognito") val contact = connectionPlan.contactAddressPlan.contact - openKnownContact(chatModel, rhId, close, contact) - AlertManager.privacySensitive.showAlertMsg( - generalGetString(MR.strings.contact_already_exists), - String.format(generalGetString(MR.strings.connect_plan_you_are_already_connecting_to_vName), contact.displayName), - hostDevice = hostDevice(rhId), - ) + if (filterKnownContact != null) { + filterKnownContact(contact) + } else { + openKnownContact(chatModel, rhId, close, contact) + AlertManager.privacySensitive.showAlertMsg( + generalGetString(MR.strings.contact_already_exists), + String.format(generalGetString(MR.strings.connect_plan_you_are_already_connecting_to_vName), contact.displayName) + linkText, + hostDevice = hostDevice(rhId), + ) + cleanup?.invoke() + } } is ContactAddressPlan.Known -> { Log.d(TAG, "planAndConnect, .ContactAddress, .Known, incognito=$incognito") val contact = connectionPlan.contactAddressPlan.contact - openKnownContact(chatModel, rhId, close, contact) - AlertManager.privacySensitive.showAlertMsg( - generalGetString(MR.strings.contact_already_exists), - String.format(generalGetString(MR.strings.you_are_already_connected_to_vName_via_this_link), contact.displayName), - hostDevice = hostDevice(rhId), - ) + if (filterKnownContact != null) { + filterKnownContact(contact) + } else { + openKnownContact(chatModel, rhId, close, contact) + AlertManager.privacySensitive.showAlertMsg( + generalGetString(MR.strings.contact_already_exists), + String.format(generalGetString(MR.strings.you_are_already_connected_to_vName_via_this_link), contact.displayName) + linkText, + hostDevice = hostDevice(rhId), + ) + cleanup?.invoke() + } } is ContactAddressPlan.ContactViaAddress -> { Log.d(TAG, "planAndConnect, .ContactAddress, .ContactViaAddress, incognito=$incognito") @@ -187,6 +212,7 @@ suspend fun planAndConnect( } else { askCurrentOrIncognitoProfileConnectContactViaAddress(chatModel, rhId, contact, close, openChat = false) } + cleanup?.invoke() } } is ConnectionPlan.GroupLink -> when (connectionPlan.groupLinkPlan) { @@ -195,33 +221,42 @@ suspend fun planAndConnect( if (incognito != null) { AlertManager.privacySensitive.showAlertDialog( title = generalGetString(MR.strings.connect_via_group_link), - text = generalGetString(MR.strings.you_will_join_group), + text = generalGetString(MR.strings.you_will_join_group) + linkText, confirmText = if (incognito) generalGetString(MR.strings.join_group_incognito_button) else generalGetString(MR.strings.join_group_button), - onConfirm = { withApi { connectViaUri(chatModel, rhId, uri, incognito, connectionPlan, close) } }, + onConfirm = { withBGApi { connectViaUri(chatModel, rhId, uri, incognito, connectionPlan, close, cleanup) } }, + onDismiss = cleanup, + onDismissRequest = cleanup, hostDevice = hostDevice(rhId), ) } else { askCurrentOrIncognitoProfileAlert( chatModel, rhId, uri, connectionPlan, close, title = generalGetString(MR.strings.connect_via_group_link), - text = AnnotatedString(generalGetString(MR.strings.you_will_join_group)), - connectDestructive = false + text = generalGetString(MR.strings.you_will_join_group) + linkText, + connectDestructive = false, + cleanup = cleanup, ) } } is GroupLinkPlan.OwnLink -> { Log.d(TAG, "planAndConnect, .GroupLink, .OwnLink, incognito=$incognito") val groupInfo = connectionPlan.groupLinkPlan.groupInfo - ownGroupLinkConfirmConnect(chatModel, rhId, uri, incognito, connectionPlan, groupInfo, close) + if (filterKnownGroup != null) { + filterKnownGroup(groupInfo) + } else { + ownGroupLinkConfirmConnect(chatModel, rhId, uri, linkText, incognito, connectionPlan, groupInfo, close, cleanup) + } } GroupLinkPlan.ConnectingConfirmReconnect -> { Log.d(TAG, "planAndConnect, .GroupLink, .ConnectingConfirmReconnect, incognito=$incognito") if (incognito != null) { AlertManager.privacySensitive.showAlertDialog( title = generalGetString(MR.strings.connect_plan_repeat_join_request), - text = generalGetString(MR.strings.connect_plan_you_are_already_joining_the_group_via_this_link), + text = generalGetString(MR.strings.connect_plan_you_are_already_joining_the_group_via_this_link) + linkText, confirmText = if (incognito) generalGetString(MR.strings.join_group_incognito_button) else generalGetString(MR.strings.join_group_button), - onConfirm = { withApi { connectViaUri(chatModel, rhId, uri, incognito, connectionPlan, close) } }, + onConfirm = { withBGApi { connectViaUri(chatModel, rhId, uri, incognito, connectionPlan, close, cleanup) } }, + onDismiss = cleanup, + onDismissRequest = cleanup, destructive = true, hostDevice = hostDevice(rhId), ) @@ -229,8 +264,9 @@ suspend fun planAndConnect( askCurrentOrIncognitoProfileAlert( chatModel, rhId, uri, connectionPlan, close, title = generalGetString(MR.strings.connect_plan_repeat_join_request), - text = AnnotatedString(generalGetString(MR.strings.connect_plan_you_are_already_joining_the_group_via_this_link)), - connectDestructive = true + text = generalGetString(MR.strings.connect_plan_you_are_already_joining_the_group_via_this_link) + linkText, + connectDestructive = true, + cleanup = cleanup, ) } } @@ -240,37 +276,44 @@ suspend fun planAndConnect( if (groupInfo != null) { AlertManager.privacySensitive.showAlertMsg( generalGetString(MR.strings.connect_plan_group_already_exists), - String.format(generalGetString(MR.strings.connect_plan_you_are_already_joining_the_group_vName), groupInfo.displayName) + String.format(generalGetString(MR.strings.connect_plan_you_are_already_joining_the_group_vName), groupInfo.displayName) + linkText ) } else { AlertManager.privacySensitive.showAlertMsg( generalGetString(MR.strings.connect_plan_already_joining_the_group), - generalGetString(MR.strings.connect_plan_you_are_already_joining_the_group_via_this_link), + generalGetString(MR.strings.connect_plan_you_are_already_joining_the_group_via_this_link) + linkText, hostDevice = hostDevice(rhId), ) } + cleanup?.invoke() } is GroupLinkPlan.Known -> { Log.d(TAG, "planAndConnect, .GroupLink, .Known, incognito=$incognito") val groupInfo = connectionPlan.groupLinkPlan.groupInfo - openKnownGroup(chatModel, rhId, close, groupInfo) - AlertManager.privacySensitive.showAlertMsg( - generalGetString(MR.strings.connect_plan_group_already_exists), - String.format(generalGetString(MR.strings.connect_plan_you_are_already_in_group_vName), groupInfo.displayName), - hostDevice = hostDevice(rhId), - ) + if (filterKnownGroup != null) { + filterKnownGroup(groupInfo) + } else { + openKnownGroup(chatModel, rhId, close, groupInfo) + AlertManager.privacySensitive.showAlertMsg( + generalGetString(MR.strings.connect_plan_group_already_exists), + String.format(generalGetString(MR.strings.connect_plan_you_are_already_in_group_vName), groupInfo.displayName) + linkText, + hostDevice = hostDevice(rhId), + ) + cleanup?.invoke() + } } } } } else { Log.d(TAG, "planAndConnect, plan error") if (incognito != null) { - connectViaUri(chatModel, rhId, uri, incognito, connectionPlan = null, close) + connectViaUri(chatModel, rhId, uri, incognito, connectionPlan = null, close, cleanup) } else { askCurrentOrIncognitoProfileAlert( chatModel, rhId, uri, connectionPlan = null, close, title = generalGetString(MR.strings.connect_plan_connect_via_link), - connectDestructive = false + connectDestructive = false, + cleanup = cleanup, ) } } @@ -282,7 +325,8 @@ suspend fun connectViaUri( uri: URI, incognito: Boolean, connectionPlan: ConnectionPlan?, - close: (() -> Unit)? + close: (() -> Unit)?, + cleanup: (() -> Unit)?, ) { val pcc = chatModel.controller.apiConnect(rhId, incognito, uri.toString()) val connLinkType = if (connectionPlan != null) planToConnectionLinkType(connectionPlan) else ConnectionLinkType.INVITATION @@ -300,6 +344,7 @@ suspend fun connectViaUri( hostDevice = hostDevice(rhId), ) } + cleanup?.invoke() } fun planToConnectionLinkType(connectionPlan: ConnectionPlan): ConnectionLinkType { @@ -317,8 +362,9 @@ fun askCurrentOrIncognitoProfileAlert( connectionPlan: ConnectionPlan?, close: (() -> Unit)?, title: String, - text: AnnotatedString? = null, + text: String? = null, connectDestructive: Boolean, + cleanup: (() -> Unit)?, ) { AlertManager.privacySensitive.showAlertDialogButtonsColumn( title = title, @@ -328,33 +374,35 @@ fun askCurrentOrIncognitoProfileAlert( val connectColor = if (connectDestructive) MaterialTheme.colors.error else MaterialTheme.colors.primary SectionItemView({ AlertManager.privacySensitive.hideAlert() - withApi { - connectViaUri(chatModel, rhId, uri, incognito = false, connectionPlan, close) + withBGApi { + connectViaUri(chatModel, rhId, uri, incognito = false, connectionPlan, close, cleanup) } }) { Text(generalGetString(MR.strings.connect_use_current_profile), Modifier.fillMaxWidth(), textAlign = TextAlign.Center, color = connectColor) } SectionItemView({ AlertManager.privacySensitive.hideAlert() - withApi { - connectViaUri(chatModel, rhId, uri, incognito = true, connectionPlan, close) + withBGApi { + connectViaUri(chatModel, rhId, uri, incognito = true, connectionPlan, close, cleanup) } }) { Text(generalGetString(MR.strings.connect_use_new_incognito_profile), Modifier.fillMaxWidth(), textAlign = TextAlign.Center, color = connectColor) } SectionItemView({ AlertManager.privacySensitive.hideAlert() + cleanup?.invoke() }) { Text(stringResource(MR.strings.cancel_verb), Modifier.fillMaxWidth(), textAlign = TextAlign.Center, color = MaterialTheme.colors.primary) } } }, + onDismissRequest = cleanup, hostDevice = hostDevice(rhId), ) } fun openKnownContact(chatModel: ChatModel, rhId: Long?, close: (() -> Unit)?, contact: Contact) { - withApi { + withBGApi { val c = chatModel.getContactChat(contact.contactId) if (c != null) { close?.invoke() @@ -367,20 +415,23 @@ fun ownGroupLinkConfirmConnect( chatModel: ChatModel, rhId: Long?, uri: URI, + linkText: String, incognito: Boolean?, connectionPlan: ConnectionPlan?, groupInfo: GroupInfo, close: (() -> Unit)?, + cleanup: (() -> Unit)?, ) { AlertManager.privacySensitive.showAlertDialogButtonsColumn( title = generalGetString(MR.strings.connect_plan_join_your_group), - text = AnnotatedString(String.format(generalGetString(MR.strings.connect_plan_this_is_your_link_for_group_vName), groupInfo.displayName)), + text = String.format(generalGetString(MR.strings.connect_plan_this_is_your_link_for_group_vName), groupInfo.displayName) + linkText, buttons = { Column { // Open group SectionItemView({ AlertManager.privacySensitive.hideAlert() openKnownGroup(chatModel, rhId, close, groupInfo) + cleanup?.invoke() }) { Text(generalGetString(MR.strings.connect_plan_open_group), Modifier.fillMaxWidth(), textAlign = TextAlign.Center, color = MaterialTheme.colors.primary) } @@ -388,8 +439,8 @@ fun ownGroupLinkConfirmConnect( // Join incognito / Join with current profile SectionItemView({ AlertManager.privacySensitive.hideAlert() - withApi { - connectViaUri(chatModel, rhId, uri, incognito, connectionPlan, close) + withBGApi { + connectViaUri(chatModel, rhId, uri, incognito, connectionPlan, close, cleanup) } }) { Text( @@ -401,8 +452,8 @@ fun ownGroupLinkConfirmConnect( // Use current profile SectionItemView({ AlertManager.privacySensitive.hideAlert() - withApi { - connectViaUri(chatModel, rhId, uri, incognito = false, connectionPlan, close) + withBGApi { + connectViaUri(chatModel, rhId, uri, incognito = false, connectionPlan, close, cleanup) } }) { Text(generalGetString(MR.strings.connect_use_current_profile), Modifier.fillMaxWidth(), textAlign = TextAlign.Center, color = MaterialTheme.colors.error) @@ -410,8 +461,8 @@ fun ownGroupLinkConfirmConnect( // Use new incognito profile SectionItemView({ AlertManager.privacySensitive.hideAlert() - withApi { - connectViaUri(chatModel, rhId, uri, incognito = true, connectionPlan, close) + withBGApi { + connectViaUri(chatModel, rhId, uri, incognito = true, connectionPlan, close, cleanup) } }) { Text(generalGetString(MR.strings.connect_use_new_incognito_profile), Modifier.fillMaxWidth(), textAlign = TextAlign.Center, color = MaterialTheme.colors.error) @@ -420,17 +471,19 @@ fun ownGroupLinkConfirmConnect( // Cancel SectionItemView({ AlertManager.privacySensitive.hideAlert() + cleanup?.invoke() }) { Text(stringResource(MR.strings.cancel_verb), Modifier.fillMaxWidth(), textAlign = TextAlign.Center, color = MaterialTheme.colors.primary) } } }, + onDismissRequest = cleanup, hostDevice = hostDevice(rhId), ) } fun openKnownGroup(chatModel: ChatModel, rhId: Long?, close: (() -> Unit)?, groupInfo: GroupInfo) { - withApi { + withBGApi { val g = chatModel.getGroupChat(groupInfo.groupId) if (g != null) { close?.invoke() @@ -438,77 +491,3 @@ fun openKnownGroup(chatModel: ChatModel, rhId: Long?, close: (() -> Unit)?, grou } } } - -@Composable -fun ConnectContactLayout( - chatModel: ChatModel, - rh: RemoteHostInfo?, - incognitoPref: SharedPreference<Boolean>, - close: () -> Unit -) { - val incognito = remember { mutableStateOf(incognitoPref.get()) } - - @Composable - fun QRCodeScanner(close: () -> Unit) { - QRCodeScanner { connReqUri -> - try { - val uri = URI(connReqUri) - withApi { - planAndConnect(chatModel, rh?.remoteHostId, uri, incognito = incognito.value, close) - } - } catch (e: RuntimeException) { - AlertManager.shared.showAlertMsg( - title = generalGetString(MR.strings.invalid_QR_code), - text = generalGetString(MR.strings.this_QR_code_is_not_a_link) - ) - } - } - } - - Column( - Modifier.verticalScroll(rememberScrollState()).padding(horizontal = DEFAULT_PADDING), - verticalArrangement = Arrangement.SpaceBetween - ) { - AppBarTitle(stringResource(MR.strings.scan_QR_code), hostDevice(rh?.remoteHostId), withPadding = false) - Box( - Modifier - .fillMaxWidth() - .aspectRatio(ratio = 1F) - .padding(bottom = 12.dp) - ) { QRCodeScanner(close) } - - IncognitoToggle(incognitoPref, incognito) { ModalManager.start.showModal { IncognitoView() } } - - SectionTextFooter( - buildAnnotatedString { - append(sharedProfileInfo(chatModel, incognito.value)) - append("\n\n") - append(annotatedStringResource(MR.strings.if_you_cannot_meet_in_person_scan_QR_in_video_call_or_ask_for_invitation_link)) - } - ) - - SectionBottomSpacer() - } -} - -fun URI.getQueryParameter(param: String): String? { - if (!query.contains("$param=")) return null - return query.substringAfter("$param=").substringBefore("&") -} - -@Preview/*( - uiMode = Configuration.UI_MODE_NIGHT_YES, - showBackground = true, - name = "Dark Mode" -)*/ -@Composable -fun PreviewConnectContactLayout() { - SimpleXTheme { - ConnectContactLayout( - chatModel = ChatModel, - rh = null, - incognitoPref = SharedPreference({ false }, {}), - close = {}, - ) - } -} diff --git a/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/views/newchat/ConnectViaLinkView.kt b/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/views/newchat/ConnectViaLinkView.kt deleted file mode 100644 index 0077e2849c..0000000000 --- a/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/views/newchat/ConnectViaLinkView.kt +++ /dev/null @@ -1,12 +0,0 @@ -package chat.simplex.common.views.newchat - -import androidx.compose.runtime.* -import chat.simplex.common.model.ChatModel -import chat.simplex.common.model.RemoteHostInfo - -enum class ConnectViaLinkTab { - SCAN, PASTE -} - -@Composable -expect fun ConnectViaLinkView(m: ChatModel, rh: RemoteHostInfo?, close: () -> Unit) diff --git a/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/views/newchat/ContactConnectionInfoView.kt b/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/views/newchat/ContactConnectionInfoView.kt index 5e9495e866..6202d8263f 100644 --- a/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/views/newchat/ContactConnectionInfoView.kt +++ b/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/views/newchat/ContactConnectionInfoView.kt @@ -23,7 +23,7 @@ import chat.simplex.common.views.chatlist.deleteContactConnectionAlert import chat.simplex.common.views.helpers.* import chat.simplex.common.model.ChatModel import chat.simplex.common.model.PendingContactConnection -import chat.simplex.common.platform.shareText +import chat.simplex.common.platform.* import chat.simplex.common.views.usersettings.* import chat.simplex.res.MR @@ -37,16 +37,19 @@ fun ContactConnectionInfoView( close: () -> Unit ) { LaunchedEffect(connReqInvitation) { - chatModel.connReqInv.value = connReqInvitation + if (connReqInvitation != null) { + chatModel.showingInvitation.value = ShowingInvitation(contactConnection.id, connReqInvitation, false) + } } - /** When [AddContactView] is open, we don't need to drop [chatModel.connReqInv]. - * Otherwise, it will be called here AFTER [AddContactView] is launched and will clear the value too soon. + /** When [AddContactLearnMore] is open, we don't need to drop [ChatModel.showingInvitation]. + * Otherwise, it will be called here AFTER [AddContactLearnMore] is launched and will clear the value too soon. * It will be dropped automatically when connection established or when user goes away from this screen. + * It applies only to Android because on Desktop center space will not be overlapped by [AddContactLearnMore] **/ DisposableEffect(Unit) { onDispose { - if (!ModalManager.center.hasModalsOpen()) { - chatModel.connReqInv.value = null + if (!ModalManager.center.hasModalsOpen() || appPlatform.isDesktop) { + chatModel.showingInvitation.value = null } } } @@ -61,14 +64,14 @@ fun ContactConnectionInfoView( onLocalAliasChanged = { setContactAlias(rhId, contactConnection, it, chatModel) }, share = { if (connReqInvitation != null) clipboard.shareText(connReqInvitation) }, learnMore = { - ModalManager.center.showModal { + ModalManager.end.showModalCloseable { close -> Column( Modifier .fillMaxHeight() .padding(horizontal = DEFAULT_PADDING), verticalArrangement = Arrangement.SpaceBetween ) { - AddContactLearnMore() + AddContactLearnMore(close) } } } @@ -135,11 +138,7 @@ private fun ContactConnectionInfoLayout( SectionView { if (!connReq.isNullOrEmpty() && contactConnection.initiated) { - SimpleXLinkQRCode( - connReq, Modifier - .padding(horizontal = DEFAULT_PADDING, vertical = DEFAULT_PADDING_HALF) - .aspectRatio(1f) - ) + SimpleXLinkQRCode(connReq) incognitoEnabled() ShareLinkButton(connReq) OneTimeLinkLearnMoreButton(learnMore) @@ -158,6 +157,30 @@ private fun ContactConnectionInfoLayout( } } +@Composable +fun ShareLinkButton(connReqInvitation: String) { + val clipboard = LocalClipboardManager.current + SettingsActionItem( + painterResource(MR.images.ic_share), + stringResource(MR.strings.share_invitation_link), + click = { + chatModel.showingInvitation.value = chatModel.showingInvitation.value?.copy(connChatUsed = true) + clipboard.shareText(simplexChatLink(connReqInvitation)) + }, + iconColor = MaterialTheme.colors.primary, + textColor = MaterialTheme.colors.primary, + ) +} + +@Composable +fun OneTimeLinkLearnMoreButton(onClick: () -> Unit) { + SettingsActionItem( + painterResource(MR.images.ic_info), + stringResource(MR.strings.learn_more), + onClick, + ) +} + @Composable fun DeleteButton(onClick: () -> Unit) { SettingsActionItem( @@ -169,7 +192,7 @@ fun DeleteButton(onClick: () -> Unit) { ) } -private fun setContactAlias(rhId: Long?, contactConnection: PendingContactConnection, localAlias: String, chatModel: ChatModel) = withApi { +private fun setContactAlias(rhId: Long?, contactConnection: PendingContactConnection, localAlias: String, chatModel: ChatModel) = withBGApi { chatModel.controller.apiSetConnectionAlias(rhId, contactConnection.pccConnId, localAlias)?.let { chatModel.updateContactConnection(rhId, it) } diff --git a/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/views/newchat/CreateLinkView.kt b/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/views/newchat/CreateLinkView.kt deleted file mode 100644 index 6f3caf4674..0000000000 --- a/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/views/newchat/CreateLinkView.kt +++ /dev/null @@ -1,118 +0,0 @@ -package chat.simplex.common.views.newchat - -import androidx.compose.foundation.layout.* -import androidx.compose.material.* -import androidx.compose.runtime.* -import androidx.compose.runtime.saveable.rememberSaveable -import androidx.compose.ui.Modifier -import androidx.compose.ui.graphics.Color -import dev.icerock.moko.resources.compose.painterResource -import dev.icerock.moko.resources.compose.stringResource -import androidx.compose.ui.unit.sp -import chat.simplex.common.model.* -import chat.simplex.common.views.helpers.* -import chat.simplex.common.views.usersettings.UserAddressView -import chat.simplex.res.MR - -enum class CreateLinkTab { - ONE_TIME, LONG_TERM -} - -@Composable -fun CreateLinkView(m: ChatModel, rh: RemoteHostInfo?, initialSelection: CreateLinkTab) { - val selection = remember { mutableStateOf(initialSelection) } - val connReqInvitation = rememberSaveable { m.connReqInv } - val contactConnection: MutableState<PendingContactConnection?> = rememberSaveable(stateSaver = serializableSaver()) { mutableStateOf(null) } - val creatingConnReq = rememberSaveable { mutableStateOf(false) } - LaunchedEffect(selection.value) { - if ( - selection.value == CreateLinkTab.ONE_TIME - && connReqInvitation.value.isNullOrEmpty() - && contactConnection.value == null - && !creatingConnReq.value - ) { - createInvitation(m, rh?.remoteHostId, creatingConnReq, connReqInvitation, contactConnection) - } - } - /** When [AddContactView] is open, we don't need to drop [chatModel.connReqInv]. - * Otherwise, it will be called here AFTER [AddContactView] is launched and will clear the value too soon. - * It will be dropped automatically when connection established or when user goes away from this screen. - **/ - DisposableEffect(Unit) { - onDispose { - if (!ModalManager.center.hasModalsOpen()) { - m.connReqInv.value = null - } - } - } - val tabTitles = CreateLinkTab.values().map { - when { - it == CreateLinkTab.ONE_TIME && connReqInvitation.value.isNullOrEmpty() && contactConnection.value == null -> - stringResource(MR.strings.create_one_time_link) - it == CreateLinkTab.ONE_TIME -> - stringResource(MR.strings.one_time_link) - it == CreateLinkTab.LONG_TERM -> - stringResource(MR.strings.your_simplex_contact_address) - else -> "" - } - } - Column( - Modifier - .fillMaxHeight(), - verticalArrangement = Arrangement.SpaceBetween - ) { - Column(Modifier.weight(1f)) { - when (selection.value) { - CreateLinkTab.ONE_TIME -> { - AddContactView(m, rh,connReqInvitation.value ?: "", contactConnection) - } - CreateLinkTab.LONG_TERM -> { - UserAddressView(m, viaCreateLinkView = true, close = {}) - } - } - } - TabRow( - selectedTabIndex = selection.value.ordinal, - backgroundColor = Color.Transparent, - contentColor = MaterialTheme.colors.primary, - ) { - tabTitles.forEachIndexed { index, it -> - Tab( - selected = selection.value.ordinal == index, - onClick = { - selection.value = CreateLinkTab.values()[index] - }, - text = { Text(it, fontSize = 13.sp) }, - icon = { - Icon( - if (CreateLinkTab.ONE_TIME.ordinal == index) painterResource(MR.images.ic_repeat_one) else painterResource(MR.images.ic_all_inclusive), - it - ) - }, - selectedContentColor = MaterialTheme.colors.primary, - unselectedContentColor = MaterialTheme.colors.secondary, - ) - } - } - } -} - -private fun createInvitation( - m: ChatModel, - rhId: Long?, - creatingConnReq: MutableState<Boolean>, - connReqInvitation: MutableState<String?>, - contactConnection: MutableState<PendingContactConnection?> -) { - creatingConnReq.value = true - withApi { - val r = m.controller.apiAddContact(rhId, incognito = m.controller.appPrefs.incognito.get()) - if (r != null) { - m.updateContactConnection(rhId, r.second) - connReqInvitation.value = r.first - contactConnection.value = r.second - } else { - creatingConnReq.value = false - } - } -} diff --git a/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/views/newchat/NewChatSheet.kt b/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/views/newchat/NewChatSheet.kt index 86929584c1..26c5422623 100644 --- a/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/views/newchat/NewChatSheet.kt +++ b/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/views/newchat/NewChatSheet.kt @@ -42,12 +42,7 @@ fun NewChatSheet(chatModel: ChatModel, newChatSheetState: StateFlow<AnimatedView addContact = { closeNewChatSheet(false) ModalManager.center.closeModals() - ModalManager.center.showModal { CreateLinkView(chatModel, chatModel.currentRemoteHost.value, CreateLinkTab.ONE_TIME) } - }, - connectViaLink = { - closeNewChatSheet(false) - ModalManager.center.closeModals() - ModalManager.center.showModalCloseable { close -> ConnectViaLinkView(chatModel, chatModel.currentRemoteHost.value, close) } + ModalManager.center.showModalCloseable { close -> NewChatView(chatModel.currentRemoteHost.value, NewChatOption.INVITE, close = close) } }, createGroup = { closeNewChatSheet(false) @@ -59,18 +54,16 @@ fun NewChatSheet(chatModel: ChatModel, newChatSheetState: StateFlow<AnimatedView } private val titles = listOf( - MR.strings.share_one_time_link, - if (appPlatform.isAndroid) MR.strings.connect_via_link_or_qr else MR.strings.connect_via_link, - MR.strings.create_group + MR.strings.add_contact_tab, + MR.strings.create_group_button ) -private val icons = listOf(MR.images.ic_add_link, MR.images.ic_qr_code, MR.images.ic_group) +private val icons = listOf(MR.images.ic_add_link, MR.images.ic_group) @Composable private fun NewChatSheetLayout( newChatSheetState: StateFlow<AnimatedViewState>, stopped: Boolean, addContact: () -> Unit, - connectViaLink: () -> Unit, createGroup: () -> Unit, closeNewChatSheet: (animated: Boolean) -> Unit, ) { @@ -109,7 +102,7 @@ private fun NewChatSheetLayout( verticalArrangement = Arrangement.Bottom, horizontalAlignment = Alignment.End ) { - val actions = remember { listOf(addContact, connectViaLink, createGroup) } + val actions = remember { listOf(addContact, createGroup) } val backgroundColor = if (isInDarkTheme()) blendARGB(MaterialTheme.colors.primary, Color.Black, 0.7F) else @@ -182,7 +175,7 @@ fun ActionButton( disabled: Boolean = false, click: () -> Unit = {} ) { - Surface(shape = RoundedCornerShape(18.dp), color = Color.Transparent) { + Surface(shape = RoundedCornerShape(18.dp), color = Color.Transparent, contentColor = LocalContentColor.current) { Column( Modifier .clickable(onClick = click) @@ -227,7 +220,7 @@ fun ActionButton( disabled: Boolean = false, click: () -> Unit = {} ) { - Surface(modifier, shape = RoundedCornerShape(18.dp)) { + Surface(modifier, shape = RoundedCornerShape(18.dp), contentColor = LocalContentColor.current) { Column( Modifier .fillMaxWidth() @@ -271,7 +264,6 @@ private fun PreviewNewChatSheet() { MutableStateFlow(AnimatedViewState.VISIBLE), stopped = false, addContact = {}, - connectViaLink = {}, createGroup = {}, closeNewChatSheet = {}, ) diff --git a/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/views/newchat/NewChatView.kt b/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/views/newchat/NewChatView.kt new file mode 100644 index 0000000000..3b4bb86e66 --- /dev/null +++ b/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/views/newchat/NewChatView.kt @@ -0,0 +1,436 @@ +package chat.simplex.common.views.newchat + +import SectionBottomSpacer +import SectionItemView +import SectionTextFooter +import SectionView +import androidx.compose.foundation.* +import androidx.compose.foundation.interaction.MutableInteractionSource +import androidx.compose.foundation.layout.* +import androidx.compose.foundation.pager.HorizontalPager +import androidx.compose.foundation.pager.rememberPagerState +import androidx.compose.foundation.text.BasicTextField +import androidx.compose.material.* +import androidx.compose.runtime.* +import androidx.compose.runtime.saveable.rememberSaveable +import androidx.compose.ui.Alignment +import androidx.compose.ui.Modifier +import androidx.compose.ui.graphics.Color +import androidx.compose.ui.platform.LocalClipboardManager +import androidx.compose.ui.text.TextStyle +import androidx.compose.ui.text.input.VisualTransformation +import androidx.compose.ui.unit.dp +import dev.icerock.moko.resources.compose.painterResource +import dev.icerock.moko.resources.compose.stringResource +import androidx.compose.ui.unit.sp +import chat.simplex.common.model.* +import chat.simplex.common.model.ChatModel.controller +import chat.simplex.common.platform.* +import chat.simplex.common.ui.theme.* +import chat.simplex.common.views.helpers.* +import chat.simplex.common.views.usersettings.* +import chat.simplex.res.MR +import kotlinx.coroutines.launch +import java.net.URI + +enum class NewChatOption { + INVITE, CONNECT +} + +@Composable +fun ModalData.NewChatView(rh: RemoteHostInfo?, selection: NewChatOption, showQRCodeScanner: Boolean = false, close: () -> Unit) { + val selection = remember { stateGetOrPut("selection") { selection } } + val showQRCodeScanner = remember { stateGetOrPut("showQRCodeScanner") { showQRCodeScanner } } + val contactConnection: MutableState<PendingContactConnection?> = rememberSaveable(stateSaver = serializableSaver()) { mutableStateOf(null) } + val connReqInvitation by remember { derivedStateOf { chatModel.showingInvitation.value?.connReq ?: "" } } + val creatingConnReq = rememberSaveable { mutableStateOf(false) } + val pastedLink = rememberSaveable { mutableStateOf("") } + LaunchedEffect(selection.value) { + if ( + selection.value == NewChatOption.INVITE + && connReqInvitation.isEmpty() + && contactConnection.value == null + && !creatingConnReq.value + ) { + createInvitation(rh?.remoteHostId, creatingConnReq, connReqInvitation, contactConnection) + } + } + DisposableEffect(Unit) { + onDispose { + /** When [AddContactLearnMore] is open, we don't need to drop [ChatModel.showingInvitation]. + * Otherwise, it will be called here AFTER [AddContactLearnMore] is launched and will clear the value too soon. + * It will be dropped automatically when connection established or when user goes away from this screen. + * It applies only to Android because on Desktop center space will not be overlapped by [AddContactLearnMore] + **/ + if (chatModel.showingInvitation.value != null && (!ModalManager.center.hasModalsOpen() || appPlatform.isDesktop)) { + val conn = contactConnection.value + if (chatModel.showingInvitation.value?.connChatUsed == false && conn != null) { + AlertManager.shared.showAlertDialog( + title = generalGetString(MR.strings.keep_unused_invitation_question), + text = generalGetString(MR.strings.you_can_view_invitation_link_again), + confirmText = generalGetString(MR.strings.delete_verb), + dismissText = generalGetString(MR.strings.keep_invitation_link), + destructive = true, + onConfirm = { + withBGApi { + val chatInfo = ChatInfo.ContactConnection(conn) + controller.deleteChat(Chat(remoteHostId = rh?.remoteHostId, chatInfo = chatInfo, chatItems = listOf())) + if (chatModel.chatId.value == chatInfo.id) { + chatModel.chatId.value = null + ModalManager.end.closeModals() + } + } + } + ) + } + chatModel.showingInvitation.value = null + } + } + } + val tabTitles = NewChatOption.values().map { + when(it) { + NewChatOption.INVITE -> + stringResource(MR.strings.add_contact_tab) + NewChatOption.CONNECT -> + stringResource(MR.strings.connect_via_link) + } + } + + Column( + Modifier.fillMaxSize(), + ) { + Box(contentAlignment = Alignment.Center) { + val bottomPadding = DEFAULT_PADDING + AppBarTitle(stringResource(MR.strings.new_chat), hostDevice(rh?.remoteHostId), bottomPadding = bottomPadding) + Column(Modifier.align(Alignment.CenterEnd).padding(bottom = bottomPadding, end = DEFAULT_PADDING)) { + AddContactLearnMoreButton() + } + } + val scope = rememberCoroutineScope() + val pagerState = rememberPagerState( + initialPage = selection.value.ordinal, + initialPageOffsetFraction = 0f + ) { NewChatOption.values().size } + KeyChangeEffect(pagerState.currentPage) { + selection.value = NewChatOption.values()[pagerState.currentPage] + } + TabRow( + selectedTabIndex = pagerState.currentPage, + backgroundColor = Color.Transparent, + contentColor = MaterialTheme.colors.primary, + ) { + tabTitles.forEachIndexed { index, it -> + LeadingIconTab( + selected = pagerState.currentPage == index, + onClick = { + scope.launch { + pagerState.animateScrollToPage(index) + } + }, + text = { Text(it, fontSize = 13.sp) }, + icon = { + Icon( + if (NewChatOption.INVITE.ordinal == index) painterResource(MR.images.ic_repeat_one) else painterResource(MR.images.ic_qr_code), + it + ) + }, + selectedContentColor = MaterialTheme.colors.primary, + unselectedContentColor = MaterialTheme.colors.secondary, + ) + } + } + + HorizontalPager(state = pagerState, Modifier.fillMaxSize(), verticalAlignment = Alignment.Top) { index -> + Column( + Modifier + .fillMaxSize() + .verticalScroll(rememberScrollState()), + verticalArrangement = if (index == NewChatOption.INVITE.ordinal && connReqInvitation.isEmpty()) Arrangement.Center else Arrangement.Top) { + Spacer(Modifier.height(DEFAULT_PADDING)) + when (index) { + NewChatOption.INVITE.ordinal -> { + PrepareAndInviteView(rh?.remoteHostId, contactConnection, connReqInvitation, creatingConnReq) + } + NewChatOption.CONNECT.ordinal -> { + ConnectView(rh?.remoteHostId, showQRCodeScanner, pastedLink, close) + } + } + SectionBottomSpacer() + } + } + } +} + +@Composable +private fun PrepareAndInviteView(rhId: Long?, contactConnection: MutableState<PendingContactConnection?>, connReqInvitation: String, creatingConnReq: MutableState<Boolean>) { + if (connReqInvitation.isNotEmpty()) { + InviteView( + rhId, + connReqInvitation = connReqInvitation, + contactConnection = contactConnection, + ) + } else if (creatingConnReq.value) { + CreatingLinkProgressView() + } else { + RetryButton { createInvitation(rhId, creatingConnReq, connReqInvitation, contactConnection) } + } +} + +@Composable +private fun CreatingLinkProgressView() { + DefaultProgressView(stringResource(MR.strings.creating_link)) +} + +@Composable +private fun RetryButton(onClick: () -> Unit) { + Column( + Modifier.fillMaxSize(), + horizontalAlignment = Alignment.CenterHorizontally, + verticalArrangement = Arrangement.Center + ) { + IconButton(onClick, Modifier.size(30.dp)) { + Icon(painterResource(MR.images.ic_refresh), null) + } + Spacer(Modifier.height(DEFAULT_PADDING)) + Text(stringResource(MR.strings.retry_verb)) + } +} + +@Composable +private fun InviteView(rhId: Long?, connReqInvitation: String, contactConnection: MutableState<PendingContactConnection?>) { + SectionView(stringResource(MR.strings.share_this_1_time_link).uppercase()) { + LinkTextView(connReqInvitation, true) + } + + Spacer(Modifier.height(10.dp)) + + SectionView(stringResource(MR.strings.or_show_this_qr_code).uppercase()) { + SimpleXLinkQRCode(connReqInvitation, onShare = { chatModel.markShowingInvitationUsed() }) + } + + Spacer(Modifier.height(10.dp)) + val incognito = remember { mutableStateOf(controller.appPrefs.incognito.get()) } + IncognitoToggle(controller.appPrefs.incognito, incognito) { + if (appPlatform.isDesktop) ModalManager.end.closeModals() + ModalManager.end.showModal { IncognitoView() } + } + KeyChangeEffect(incognito.value) { + withBGApi { + val contactConn = contactConnection.value ?: return@withBGApi + val conn = controller.apiSetConnectionIncognito(rhId, contactConn.pccConnId, incognito.value) ?: return@withBGApi + contactConnection.value = conn + chatModel.updateContactConnection(rhId, conn) + } + chatModel.markShowingInvitationUsed() + } + SectionTextFooter(sharedProfileInfo(chatModel, incognito.value)) +} + +@Composable +private fun AddContactLearnMoreButton() { + IconButton( + { + if (appPlatform.isDesktop) ModalManager.end.closeModals() + ModalManager.end.showModalCloseable { close -> + Column( + Modifier + .fillMaxHeight() + .padding(horizontal = DEFAULT_PADDING), + verticalArrangement = Arrangement.SpaceBetween + ) { + AddContactLearnMore(close) + } + } + } + ) { + Icon( + painterResource(MR.images.ic_info), + stringResource(MR.strings.learn_more), + ) + } +} + +@Composable +private fun ConnectView(rhId: Long?, showQRCodeScanner: MutableState<Boolean>, pastedLink: MutableState<String>, close: () -> Unit) { + SectionView(stringResource(MR.strings.paste_the_link_you_received).uppercase()) { + PasteLinkView(rhId, pastedLink, showQRCodeScanner, close) + } + + if (appPlatform.isAndroid) { + Spacer(Modifier.height(10.dp)) + + SectionView(stringResource(MR.strings.or_scan_qr_code).uppercase()) { + QRCodeScanner(showQRCodeScanner) { text -> + withBGApi { + val res = verify(rhId, text, close) + if (!res) { + AlertManager.shared.showAlertMsg( + title = generalGetString(MR.strings.invalid_qr_code), + text = generalGetString(MR.strings.code_you_scanned_is_not_simplex_link_qr_code) + ) + } + } + } + } + } +} + +@Composable +private fun PasteLinkView(rhId: Long?, pastedLink: MutableState<String>, showQRCodeScanner: MutableState<Boolean>, close: () -> Unit) { + if (pastedLink.value.isEmpty()) { + val clipboard = LocalClipboardManager.current + SectionItemView({ + val str = clipboard.getText()?.text ?: return@SectionItemView + val link = strHasSingleSimplexLink(str.trim()) + if (link != null) { + pastedLink.value = link.text + showQRCodeScanner.value = false + withBGApi { connect(rhId, link.text, close) { pastedLink.value = "" } } + } else { + AlertManager.shared.showAlertMsg( + title = generalGetString(MR.strings.invalid_contact_link), + text = generalGetString(MR.strings.the_text_you_pasted_is_not_a_link) + ) + } + }) { + Text(stringResource(MR.strings.tap_to_paste_link)) + } + } else { + LinkTextView(pastedLink.value, false) + } +} + +@Composable +private fun LinkTextView(link: String, share: Boolean) { + val clipboard = LocalClipboardManager.current + Row(Modifier.fillMaxWidth().heightIn(min = 46.dp).padding(horizontal = DEFAULT_PADDING), verticalAlignment = Alignment.CenterVertically) { + Box(Modifier.weight(1f).clickable { + chatModel.markShowingInvitationUsed() + clipboard.shareText(link) + }) { + BasicTextField( + value = link, + onValueChange = { }, + enabled = false, + textStyle = TextStyle(fontSize = 16.sp, color = MaterialTheme.colors.onBackground), + singleLine = true, + decorationBox = @Composable { innerTextField -> + TextFieldDefaults.TextFieldDecorationBox( + value = link, + innerTextField = innerTextField, + contentPadding = PaddingValues(), + label = null, + visualTransformation = VisualTransformation.None, + leadingIcon = null, + trailingIcon = null, + singleLine = true, + enabled = false, + isError = false, + interactionSource = remember { MutableInteractionSource() }, + ) + }) + } + // Element Text() can add ellipsis (...) in random place of the string, sometimes even after half of width of a screen. + // So using BasicTextField + manual ... + Text("…", fontSize = 16.sp) + if (share) { + Spacer(Modifier.width(DEFAULT_PADDING)) + IconButton({ + chatModel.markShowingInvitationUsed() + clipboard.shareText(link) + }, Modifier.size(20.dp)) { + Icon(painterResource(MR.images.ic_share_filled), null, tint = MaterialTheme.colors.primary) + } + } + } +} + +private suspend fun verify(rhId: Long?, text: String?, close: () -> Unit): Boolean { + if (text != null && strIsSimplexLink(text)) { + connect(rhId, text, close) + return true + } + return false +} + +private suspend fun connect(rhId: Long?, link: String, close: () -> Unit, cleanup: (() -> Unit)? = null) { + planAndConnect( + rhId, + URI.create(link), + close = close, + cleanup = cleanup, + incognito = null + ) +} + +private fun createInvitation( + rhId: Long?, + creatingConnReq: MutableState<Boolean>, + connReqInvitation: String, + contactConnection: MutableState<PendingContactConnection?> +) { + if (connReqInvitation.isNotEmpty() || contactConnection.value != null || creatingConnReq.value) return + creatingConnReq.value = true + withBGApi { + val (r, alert) = controller.apiAddContact(rhId, incognito = controller.appPrefs.incognito.get()) + if (r != null) { + chatModel.updateContactConnection(rhId, r.second) + chatModel.showingInvitation.value = ShowingInvitation(connId = r.second.id, connReq = simplexChatLink(r.first), connChatUsed = false) + contactConnection.value = r.second + } else { + creatingConnReq.value = false + if (alert != null) { + alert() + } + } + } +} + +fun strIsSimplexLink(str: String): Boolean { + val parsedMd = parseToMarkdown(str) + return parsedMd != null && parsedMd.size == 1 && parsedMd[0].format is Format.SimplexLink +} + +fun strHasSingleSimplexLink(str: String): FormattedText? { + val parsedMd = parseToMarkdown(str) ?: return null + val parsedLinks = parsedMd.filter { it.format?.isSimplexLink ?: false } + if (parsedLinks.size != 1) return null + + return parsedLinks[0] +} + +@Composable +fun IncognitoToggle( + incognitoPref: SharedPreference<Boolean>, + incognito: MutableState<Boolean>, + onClickInfo: () -> Unit +) { + SettingsActionItemWithContent( + icon = if (incognito.value) painterResource(MR.images.ic_theater_comedy_filled) else painterResource(MR.images.ic_theater_comedy), + text = null, + click = onClickInfo, + iconColor = if (incognito.value) Indigo else MaterialTheme.colors.secondary, + extraPadding = false + ) { + SharedPreferenceToggleWithIcon( + stringResource(MR.strings.incognito), + painterResource(MR.images.ic_info), + stopped = false, + onClickInfo = onClickInfo, + preference = incognitoPref, + preferenceState = incognito + ) + } +} + +fun sharedProfileInfo( + chatModel: ChatModel, + incognito: Boolean +): String { + val name = chatModel.currentUser.value?.displayName ?: "" + return if (incognito) { + generalGetString(MR.strings.connect__a_new_random_profile_will_be_shared) + } else { + String.format(generalGetString(MR.strings.connect__your_profile_will_be_shared), name) + } +} diff --git a/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/views/newchat/PasteToConnect.kt b/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/views/newchat/PasteToConnect.kt deleted file mode 100644 index dacf937575..0000000000 --- a/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/views/newchat/PasteToConnect.kt +++ /dev/null @@ -1,135 +0,0 @@ -package chat.simplex.common.views.newchat - -import SectionBottomSpacer -import SectionTextFooter -import androidx.compose.desktop.ui.tooling.preview.Preview -import androidx.compose.foundation.layout.* -import androidx.compose.foundation.rememberScrollState -import androidx.compose.foundation.verticalScroll -import androidx.compose.material.MaterialTheme -import androidx.compose.runtime.* -import androidx.compose.ui.Modifier -import dev.icerock.moko.resources.compose.painterResource -import dev.icerock.moko.resources.compose.stringResource -import androidx.compose.ui.platform.LocalClipboardManager -import androidx.compose.ui.text.buildAnnotatedString -import androidx.compose.ui.unit.dp -import chat.simplex.common.model.* -import chat.simplex.common.ui.theme.* -import chat.simplex.common.views.helpers.* -import chat.simplex.common.views.usersettings.IncognitoView -import chat.simplex.common.views.usersettings.SettingsActionItem -import chat.simplex.res.MR -import java.net.URI - -@Composable -fun PasteToConnectView(chatModel: ChatModel, rh: RemoteHostInfo?, close: () -> Unit) { - val connectionLink = remember { mutableStateOf("") } - val clipboard = LocalClipboardManager.current - PasteToConnectLayout( - chatModel = chatModel, - rh = rh, - incognitoPref = chatModel.controller.appPrefs.incognito, - connectionLink = connectionLink, - pasteFromClipboard = { - connectionLink.value = clipboard.getText()?.text ?: return@PasteToConnectLayout - }, - close = close - ) -} - -@Composable -fun PasteToConnectLayout( - chatModel: ChatModel, - rh: RemoteHostInfo?, - incognitoPref: SharedPreference<Boolean>, - connectionLink: MutableState<String>, - pasteFromClipboard: () -> Unit, - close: () -> Unit -) { - val incognito = remember { mutableStateOf(incognitoPref.get()) } - val rhId = rh?.remoteHostId - fun connectViaLink(connReqUri: String) { - try { - val uri = URI(connReqUri) - withApi { - planAndConnect(chatModel, rhId, uri, incognito = incognito.value, close) - } - } catch (e: RuntimeException) { - AlertManager.shared.showAlertMsg( - title = generalGetString(MR.strings.invalid_connection_link), - text = generalGetString(MR.strings.this_string_is_not_a_connection_link) - ) - } - } - - Column( - Modifier.verticalScroll(rememberScrollState()).padding(horizontal = DEFAULT_PADDING), - verticalArrangement = Arrangement.SpaceBetween, - ) { - AppBarTitle(stringResource(MR.strings.connect_via_link), hostDevice(rhId), withPadding = false) - - Box(Modifier.padding(top = DEFAULT_PADDING, bottom = 6.dp)) { - TextEditor( - connectionLink, - Modifier.height(180.dp), - contentPadding = PaddingValues(), - placeholder = stringResource(MR.strings.paste_the_link_you_received_to_connect_with_your_contact) - ) - } - - if (connectionLink.value == "") { - SettingsActionItem( - painterResource(MR.images.ic_content_paste), - stringResource(MR.strings.paste_button), - click = pasteFromClipboard, - ) - } else { - SettingsActionItem( - painterResource(MR.images.ic_close), - stringResource(MR.strings.clear_verb), - click = { connectionLink.value = "" }, - ) - } - - SettingsActionItem( - painterResource(MR.images.ic_link), - stringResource(MR.strings.connect_button), - click = { connectViaLink(connectionLink.value) }, - textColor = MaterialTheme.colors.primary, - iconColor = MaterialTheme.colors.primary, - disabled = connectionLink.value.isEmpty() || connectionLink.value.trim().contains(" ") - ) - - IncognitoToggle(incognitoPref, incognito) { ModalManager.start.showModal { IncognitoView() } } - - SectionTextFooter( - buildAnnotatedString { - append(sharedProfileInfo(chatModel, incognito.value)) - append("\n\n") - append(annotatedStringResource(MR.strings.you_can_also_connect_by_clicking_the_link)) - } - ) - - SectionBottomSpacer() - } -} - - -@Preview/*( - uiMode = Configuration.UI_MODE_NIGHT_YES, - name = "Dark Mode" -)*/ -@Composable -fun PreviewPasteToConnectTextbox() { - SimpleXTheme { - PasteToConnectLayout( - chatModel = ChatModel, - rh = null, - incognitoPref = SharedPreference({ false }, {}), - connectionLink = remember { mutableStateOf("") }, - pasteFromClipboard = {}, - close = {} - ) - } -} diff --git a/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/views/newchat/QRCode.kt b/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/views/newchat/QRCode.kt index 7f9fae60a3..e38c983487 100644 --- a/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/views/newchat/QRCode.kt +++ b/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/views/newchat/QRCode.kt @@ -14,7 +14,7 @@ import boofcv.alg.drawing.FiducialImageEngine import boofcv.alg.fiducial.qrcode.* import chat.simplex.common.model.CryptoFile import chat.simplex.common.platform.* -import chat.simplex.common.ui.theme.SimpleXTheme +import chat.simplex.common.ui.theme.* import chat.simplex.common.views.helpers.* import chat.simplex.res.MR import kotlinx.coroutines.launch @@ -23,14 +23,18 @@ import kotlinx.coroutines.launch fun SimpleXLinkQRCode( connReq: String, modifier: Modifier = Modifier, + padding: PaddingValues = PaddingValues(horizontal = DEFAULT_PADDING * 2f, vertical = DEFAULT_PADDING_HALF), tintColor: Color = Color(0xff062d56), - withLogo: Boolean = true + withLogo: Boolean = true, + onShare: (() -> Unit)? = null, ) { QRCode( simplexChatLink(connReq), modifier, + padding, tintColor, - withLogo + withLogo, + onShare, ) } @@ -46,22 +50,24 @@ fun simplexChatLink(uri: String): String { fun QRCode( connReq: String, modifier: Modifier = Modifier, + padding: PaddingValues = PaddingValues(horizontal = DEFAULT_PADDING * 2f, vertical = DEFAULT_PADDING_HALF), tintColor: Color = Color(0xff062d56), - withLogo: Boolean = true + withLogo: Boolean = true, + onShare: (() -> Unit)? = null, ) { val scope = rememberCoroutineScope() - - BoxWithConstraints(Modifier.fillMaxWidth(), contentAlignment = Alignment.Center) { - val maxWidthInPx = with(LocalDensity.current) { maxWidth.roundToPx() } - val qr = remember(maxWidthInPx, connReq, tintColor, withLogo) { - qrCodeBitmap(connReq, maxWidthInPx).replaceColor(Color.Black.toArgb(), tintColor.toArgb()) - .let { if (withLogo) it.addLogo() else it } - } + val qr = remember(connReq, tintColor, withLogo) { + qrCodeBitmap(connReq, 1024).replaceColor(Color.Black.toArgb(), tintColor.toArgb()) + .let { if (withLogo) it.addLogo() else it } + } + Box(Modifier.fillMaxWidth(), contentAlignment = Alignment.Center) { Image( bitmap = qr, contentDescription = stringResource(MR.strings.image_descr_qr_code), Modifier - .widthIn(max = 360.dp) + .padding(padding) + .widthIn(max = 400.dp) + .aspectRatio(1f) .then(modifier) .clickable { scope.launch { @@ -70,6 +76,7 @@ fun QRCode( val file = saveTempImageUncompressed(image, true) if (file != null) { shareFile("", CryptoFile.plain(file.absolutePath)) + onShare?.invoke() } } } @@ -81,7 +88,9 @@ fun qrCodeBitmap(content: String, size: Int = 1024): ImageBitmap { val qrCode = QrCodeEncoder().addAutomatic(content).setError(QrCode.ErrorLevel.L).fixate() /** See [QrCodeGeneratorImage.initialize] and [FiducialImageEngine.configure] for size calculation */ val numModules = QrCode.totalModules(qrCode.version) - val borderModule = 1 + // Hide border on light themes to make it fit to the same place as camera in QRCodeScanner. + // On dark themes better to show the border + val borderModule = if (CurrentColors.value.colors.isLight) 0 else 1 // val calculatedFinalWidth = (pixelsPerModule * numModules) + 2 * (borderModule * pixelsPerModule) // size = (x * numModules) + 2 * (borderModule * x) // size / x = numModules + 2 * borderModule diff --git a/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/views/newchat/QRCodeScanner.kt b/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/views/newchat/QRCodeScanner.kt index 66ba595e17..1e497e0581 100644 --- a/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/views/newchat/QRCodeScanner.kt +++ b/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/views/newchat/QRCodeScanner.kt @@ -1,6 +1,14 @@ package chat.simplex.common.views.newchat +import androidx.compose.foundation.layout.PaddingValues import androidx.compose.runtime.* +import androidx.compose.ui.unit.dp +import chat.simplex.common.ui.theme.DEFAULT_PADDING +import chat.simplex.common.ui.theme.DEFAULT_PADDING_HALF @Composable -expect fun QRCodeScanner(onBarcode: (String) -> Unit) +expect fun QRCodeScanner( + showQRCodeScanner: MutableState<Boolean> = remember { mutableStateOf(true) }, + padding: PaddingValues = PaddingValues(horizontal = DEFAULT_PADDING * 2f, vertical = DEFAULT_PADDING_HALF), + onBarcode: (String) -> Unit +) diff --git a/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/views/onboarding/CreateSimpleXAddress.kt b/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/views/onboarding/CreateSimpleXAddress.kt index 8534198028..190b962eae 100644 --- a/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/views/onboarding/CreateSimpleXAddress.kt +++ b/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/views/onboarding/CreateSimpleXAddress.kt @@ -43,7 +43,7 @@ fun CreateSimpleXAddress(m: ChatModel, rhId: Long?) { ) }, createAddress = { - withApi { + withBGApi { progressIndicator = true val connReqContact = m.controller.apiCreateUserAddress(rhId) if (connReqContact != null) { @@ -84,7 +84,7 @@ private fun CreateSimpleXAddressLayout( Spacer(Modifier.weight(1f)) if (userAddress != null) { - SimpleXLinkQRCode(userAddress.connReqContact, Modifier.padding(horizontal = DEFAULT_PADDING, vertical = DEFAULT_PADDING_HALF).aspectRatio(1f)) + SimpleXLinkQRCode(userAddress.connReqContact) ShareAddressButton { share(simplexChatLink(userAddress.connReqContact)) } Spacer(Modifier.weight(1f)) ShareViaEmailButton { sendEmail(userAddress) } @@ -170,20 +170,9 @@ private fun ProgressIndicator() { private fun prepareChatBeforeAddressCreation(rhId: Long?) { if (chatModel.users.isNotEmpty()) return - withApi { - val user = chatModel.controller.apiGetActiveUser(rhId) ?: return@withApi + withBGApi { + val user = chatModel.controller.apiGetActiveUser(rhId) ?: return@withBGApi chatModel.currentUser.value = user - if (chatModel.users.isEmpty()) { - if (appPlatform.isDesktop) { - // Make possible to use chat after going to remote device linking and returning back to local profile creation - chatModel.chatRunning.value = false - } - chatModel.controller.startChat(user) - } else { - val users = chatModel.controller.listUsers(rhId) - chatModel.users.clear() - chatModel.users.addAll(users) - chatModel.controller.getUserChatData(rhId) - } + chatModel.controller.startChat(user) } } diff --git a/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/views/onboarding/HowItWorks.kt b/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/views/onboarding/HowItWorks.kt index 6c76acc3e8..14b36d0718 100644 --- a/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/views/onboarding/HowItWorks.kt +++ b/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/views/onboarding/HowItWorks.kt @@ -78,17 +78,6 @@ fun ReadableText(text: String, textAlign: TextAlign = TextAlign.Start, padding: Text(text, modifier = Modifier.padding(padding), textAlign = textAlign, lineHeight = 22.sp) } -@Composable -fun ReadableMarkdownText(text: String, textAlign: TextAlign = TextAlign.Start, padding: PaddingValues = PaddingValues(bottom = 12.dp)) { - MarkdownText( - text, - formattedText = remember(text) { parseToMarkdown(text) }, - modifier = Modifier.padding(padding), - style = TextStyle(textAlign = textAlign, lineHeight = 22.sp, fontSize = 16.sp), - linkMode = ChatController.appPrefs.simplexLinkMode.get(), - ) -} - @Preview/*( uiMode = Configuration.UI_MODE_NIGHT_YES, showBackground = true, diff --git a/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/views/onboarding/SetupDatabasePassphrase.kt b/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/views/onboarding/SetupDatabasePassphrase.kt index a51d9c8a0c..8547704893 100644 --- a/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/views/onboarding/SetupDatabasePassphrase.kt +++ b/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/views/onboarding/SetupDatabasePassphrase.kt @@ -50,7 +50,7 @@ fun SetupDatabasePassphrase(m: ChatModel) { confirmNewKey, progressIndicator, onConfirmEncrypt = { - withApi { + withLongRunningApi(slow = 30_000, deadlock = 60_000) { if (m.chatRunning.value == true) { // Stop chat if it's started before doing anything stopChatAsync(m) diff --git a/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/views/onboarding/WhatsNewView.kt b/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/views/onboarding/WhatsNewView.kt index e1a81d925c..38805472f2 100644 --- a/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/views/onboarding/WhatsNewView.kt +++ b/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/views/onboarding/WhatsNewView.kt @@ -36,7 +36,7 @@ fun WhatsNewView(viaSettings: Boolean = false, close: () -> Unit) { Icon( painterResource(MR.images.ic_open_in_new), stringResource(titleId), tint = MaterialTheme.colors.primary, modifier = Modifier - .clickable { uriHandler.openUriCatching(link) } + .clickable { if (link.startsWith("simplex:")) uriHandler.openVerifiedSimplexUri(link) else uriHandler.openUriCatching(link) } ) } @@ -462,6 +462,39 @@ private val versionDescriptions: List<VersionDescription> = listOf( ) ) ), + VersionDescription( + version = "v5.5", + post = "https://simplex.chat/blog/20240124-simplex-chat-infrastructure-costs-v5-5-simplex-ux-private-notes-group-history.html", + features = listOf( + FeatureDescription( + icon = MR.images.ic_folder_pen, + titleId = MR.strings.v5_5_private_notes, + descrId = MR.strings.v5_5_private_notes_descr + ), + FeatureDescription( + icon = MR.images.ic_link, + titleId = MR.strings.v5_5_simpler_connect_ui, + descrId = MR.strings.v5_5_simpler_connect_ui_descr + ), + FeatureDescription( + icon = MR.images.ic_forum, + titleId = MR.strings.v5_5_join_group_conversation, + descrId = MR.strings.v5_5_join_group_conversation_descr, + link = "simplex:/contact#/?v=1-4&smp=smp%3A%2F%2Fu2dS9sG8nMNURyZwqASV4yROM28Er0luVTx5X1CsMrU%3D%40smp4.simplex.im%2FeXSPwqTkKyDO3px4fLf1wx3MvPdjdLW3%23%2F%3Fv%3D1-2%26dh%3DMCowBQYDK2VuAyEAaiv6MkMH44L2TcYrt_CsX3ZvM11WgbMEUn0hkIKTOho%253D%26srv%3Do5vmywmrnaxalvz6wi3zicyftgio6psuvyniis6gco6bp6ekl4cqj4id.onion" + ), + FeatureDescription( + icon = MR.images.ic_battery_3_bar, + titleId = MR.strings.v5_5_message_delivery, + descrId = MR.strings.v5_5_message_delivery_descr + ), + FeatureDescription( + icon = MR.images.ic_translate, + titleId = MR.strings.v5_5_new_interface_languages, + descrId = MR.strings.whats_new_thanks_to_users_contribute_weblate, + link = "https://github.com/simplex-chat/simplex-chat/tree/stable#help-translating-simplex-chat" + ) + ) + ), ) private val lastVersion = versionDescriptions.last().version diff --git a/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/views/remote/ConnectDesktopView.kt b/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/views/remote/ConnectDesktopView.kt index 44e6969b8d..5acb240cb3 100644 --- a/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/views/remote/ConnectDesktopView.kt +++ b/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/views/remote/ConnectDesktopView.kt @@ -339,16 +339,9 @@ private fun DevicesView(deviceName: String, remoteCtrls: SnapshotStateList<Remot @Composable private fun ScanDesktopAddressView(sessionAddress: MutableState<String>) { SectionView(stringResource(MR.strings.scan_qr_code_from_desktop).uppercase()) { - Box( - Modifier - .fillMaxWidth() - .aspectRatio(ratio = 1F) - .padding(DEFAULT_PADDING) - ) { - QRCodeScanner { text -> - sessionAddress.value = text - processDesktopQRCode(sessionAddress, text) - } + QRCodeScanner { text -> + sessionAddress.value = text + processDesktopQRCode(sessionAddress, text) } } } diff --git a/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/views/remote/ConnectMobileView.kt b/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/views/remote/ConnectMobileView.kt index a3218c961b..bf7884e9d8 100644 --- a/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/views/remote/ConnectMobileView.kt +++ b/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/views/remote/ConnectMobileView.kt @@ -38,7 +38,9 @@ import chat.simplex.common.views.usersettings.* import chat.simplex.res.MR import dev.icerock.moko.resources.compose.painterResource import dev.icerock.moko.resources.compose.stringResource +import kotlinx.coroutines.delay import kotlinx.coroutines.flow.distinctUntilChanged +import kotlinx.coroutines.runBlocking @Composable fun ConnectMobileView() { @@ -46,7 +48,9 @@ fun ConnectMobileView() { val remoteHosts = remember { chatModel.remoteHosts } val deviceName = chatModel.controller.appPrefs.deviceNameForRemoteAccess LaunchedEffect(Unit) { - controller.reloadRemoteHosts() + withBGApi { + controller.reloadRemoteHosts() + } } ConnectMobileLayout( deviceName = remember { deviceName.state }, @@ -187,11 +191,7 @@ private fun ConnectMobileViewLayout( SectionView { if (invitation != null && sessionCode == null && port != null) { Box { - QRCode( - invitation, Modifier - .padding(start = DEFAULT_PADDING, top = DEFAULT_PADDING_HALF, end = DEFAULT_PADDING, bottom = DEFAULT_PADDING_HALF) - .aspectRatio(1f) - ) + QRCode(invitation) if (staleQrCode) { Box(Modifier.matchParentSize().background(MaterialTheme.colors.background.copy(alpha = 0.9f)), contentAlignment = Alignment.Center) { SimpleButtonDecorated(stringResource(MR.strings.refresh_qr_code), painterResource(MR.images.ic_refresh), click = refreshQrCode) diff --git a/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/views/usersettings/AdvancedNetworkSettings.kt b/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/views/usersettings/AdvancedNetworkSettings.kt index 5fb8bfb03e..7683f0ed18 100644 --- a/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/views/usersettings/AdvancedNetworkSettings.kt +++ b/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/views/usersettings/AdvancedNetworkSettings.kt @@ -92,7 +92,7 @@ fun AdvancedNetworkSettingsView(chatModel: ChatModel) { } fun saveCfg(cfg: NetCfg) { - withApi { + withBGApi { chatModel.controller.apiSetNetworkConfig(cfg) currentCfg.value = cfg chatModel.controller.setNetCfg(cfg) @@ -380,7 +380,8 @@ fun SettingsSectionFooter(revert: () -> Unit, save: () -> Unit, disabled: Boolea fun FooterButton(icon: Painter, title: String, action: () -> Unit, disabled: Boolean) { Surface( shape = RoundedCornerShape(20.dp), - color = Color.Black.copy(alpha = 0f) + color = Color.Black.copy(alpha = 0f), + contentColor = LocalContentColor.current ) { val modifier = if (disabled) Modifier else Modifier.clickable { action() } Row( diff --git a/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/views/usersettings/Appearance.kt b/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/views/usersettings/Appearance.kt index 75e7d72016..62216761ed 100644 --- a/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/views/usersettings/Appearance.kt +++ b/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/views/usersettings/Appearance.kt @@ -131,7 +131,7 @@ object AppearanceScope { SectionItemView({ val overrides = ThemeManager.currentThemeOverridesForExport(isInDarkTheme) theme.value = yaml.encodeToString<ThemeOverrides>(overrides) - withApi { exportThemeLauncher.launch("simplex.theme")} + withLongRunningApi { exportThemeLauncher.launch("simplex.theme")} }) { Text(generalGetString(MR.strings.export_theme), color = colors.primary) } @@ -144,7 +144,7 @@ object AppearanceScope { } } // Can not limit to YAML mime type since it's unsupported by Android - SectionItemView({ withApi { importThemeLauncher.launch("*/*") } }) { + SectionItemView({ withLongRunningApi { importThemeLauncher.launch("*/*") } }) { Text(generalGetString(MR.strings.import_theme), color = colors.primary) } } @@ -208,6 +208,7 @@ object AppearanceScope { "es" to "Español", "fi" to "Suomi", "fr" to "Français", + "hu" to "Magyar", "it" to "Italiano", "iw" to "עִברִית", "ja" to "日本語", @@ -216,6 +217,7 @@ object AppearanceScope { "pt-BR" to "Português, Brasil", "ru" to "Русский", "th" to "ภาษาไทย", + "tr" to "Türkçe", "uk" to "Українська", "zh-CN" to "简体中文" ) diff --git a/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/views/usersettings/DeveloperView.kt b/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/views/usersettings/DeveloperView.kt index 969a6d9d9f..cc268e9a9d 100644 --- a/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/views/usersettings/DeveloperView.kt +++ b/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/views/usersettings/DeveloperView.kt @@ -1,6 +1,7 @@ package chat.simplex.common.views.usersettings import SectionBottomSpacer +import SectionSpacer import SectionTextFooter import SectionView import androidx.compose.foundation.layout.Column @@ -22,7 +23,7 @@ import chat.simplex.res.MR @Composable fun DeveloperView( m: ChatModel, - showCustomModal: (@Composable (ChatModel, () -> Unit) -> Unit) -> (() -> Unit), + showCustomModal: (@Composable ModalData.(ChatModel, () -> Unit) -> Unit) -> (() -> Unit), withAuth: (title: String, desc: String, block: () -> Unit) -> Unit ) { Column(Modifier.fillMaxWidth().verticalScroll(rememberScrollState())) { @@ -30,28 +31,34 @@ fun DeveloperView( AppBarTitle(stringResource(MR.strings.settings_developer_tools)) val developerTools = m.controller.appPrefs.developerTools val devTools = remember { developerTools.state } - SectionView() { + SectionView { InstallTerminalAppItem(uriHandler) - ChatConsoleItem { withAuth(generalGetString(MR.strings.auth_open_chat_console), generalGetString(MR.strings.auth_log_in_using_credential), showCustomModal { it, close -> TerminalView(it, close) })} - SettingsPreferenceItem(painterResource(MR.images.ic_drive_folder_upload), stringResource(MR.strings.confirm_database_upgrades), m.controller.appPrefs.confirmDBUpgrades) + ChatConsoleItem { withAuth(generalGetString(MR.strings.auth_open_chat_console), generalGetString(MR.strings.auth_log_in_using_credential), showCustomModal { it, close -> TerminalView(it, close) }) } SettingsPreferenceItem(painterResource(MR.images.ic_code), stringResource(MR.strings.show_developer_options), developerTools) - if (appPlatform.isDesktop && devTools.value) { - TerminalAlwaysVisibleItem(m.controller.appPrefs.terminalAlwaysVisible) { checked -> - if (checked) { - withAuth(generalGetString(MR.strings.auth_open_chat_console), generalGetString(MR.strings.auth_log_in_using_credential)) { - m.controller.appPrefs.terminalAlwaysVisible.set(true) + SectionTextFooter( + generalGetString(if (devTools.value) MR.strings.show_dev_options else MR.strings.hide_dev_options) + " " + + generalGetString(MR.strings.developer_options) + ) + } + if (devTools.value) { + SectionSpacer() + SectionView(stringResource(MR.strings.developer_options_section).uppercase()) { + SettingsPreferenceItem(painterResource(MR.images.ic_drive_folder_upload), stringResource(MR.strings.confirm_database_upgrades), m.controller.appPrefs.confirmDBUpgrades) + if (appPlatform.isDesktop) { + TerminalAlwaysVisibleItem(m.controller.appPrefs.terminalAlwaysVisible) { checked -> + if (checked) { + withAuth(generalGetString(MR.strings.auth_open_chat_console), generalGetString(MR.strings.auth_log_in_using_credential)) { + m.controller.appPrefs.terminalAlwaysVisible.set(true) + } + } else { + m.controller.appPrefs.terminalAlwaysVisible.set(false) } - } else { - m.controller.appPrefs.terminalAlwaysVisible.set(false) } } SettingsPreferenceItem(painterResource(MR.images.ic_report), stringResource(MR.strings.show_internal_errors), appPreferences.showInternalErrors) + SettingsPreferenceItem(painterResource(MR.images.ic_avg_pace), stringResource(MR.strings.show_slow_api_calls), appPreferences.showSlowApiCalls) } } - SectionTextFooter( - generalGetString(if (devTools.value) MR.strings.show_dev_options else MR.strings.hide_dev_options) + " " + - generalGetString(MR.strings.developer_options) - ) SectionBottomSpacer() } } diff --git a/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/views/usersettings/IncognitoView.kt b/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/views/usersettings/IncognitoView.kt index e264172f9c..6da0d34bd3 100644 --- a/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/views/usersettings/IncognitoView.kt +++ b/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/views/usersettings/IncognitoView.kt @@ -11,6 +11,7 @@ import androidx.compose.ui.unit.dp import chat.simplex.common.ui.theme.DEFAULT_PADDING import chat.simplex.common.views.helpers.AppBarTitle import chat.simplex.common.views.helpers.generalGetString +import chat.simplex.common.views.onboarding.ReadableTextWithLink import chat.simplex.res.MR @Composable @@ -31,6 +32,7 @@ fun IncognitoLayout() { Text(generalGetString(MR.strings.incognito_info_protects)) Text(generalGetString(MR.strings.incognito_info_allows)) Text(generalGetString(MR.strings.incognito_info_share)) + ReadableTextWithLink(MR.strings.read_more_in_user_guide_with_link, "https://simplex.chat/docs/guide/chat-profiles.html#incognito-mode") SectionBottomSpacer() } } diff --git a/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/views/usersettings/NetworkAndServers.kt b/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/views/usersettings/NetworkAndServers.kt index fcd602ee2c..7c921d7e8c 100644 --- a/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/views/usersettings/NetworkAndServers.kt +++ b/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/views/usersettings/NetworkAndServers.kt @@ -37,7 +37,7 @@ fun NetworkAndServersView( chatModel: ChatModel, showModal: (@Composable (ChatModel) -> Unit) -> (() -> Unit), showSettingsModal: (@Composable (ChatModel) -> Unit) -> (() -> Unit), - showCustomModal: (@Composable (ChatModel, () -> Unit) -> Unit) -> (() -> Unit), + showCustomModal: (@Composable ModalData.(ChatModel, () -> Unit) -> Unit) -> (() -> Unit), ) { val currentRemoteHost by remember { chatModel.currentRemoteHost } // It's not a state, just a one-time value. Shouldn't be used in any state-related situations @@ -69,7 +69,7 @@ fun NetworkAndServersView( text = generalGetString(MR.strings.network_enable_socks_info).format(proxyPort.value), confirmText = generalGetString(MR.strings.confirm_verb), onConfirm = { - withApi { + withBGApi { val conf = NetCfg.proxyDefaults.withHostPort(chatModel.controller.appPrefs.networkProxyHostPort.get()) chatModel.controller.apiSetNetworkConfig(conf) chatModel.controller.setNetCfg(conf) @@ -84,7 +84,7 @@ fun NetworkAndServersView( text = generalGetString(MR.strings.network_disable_socks_info), confirmText = generalGetString(MR.strings.confirm_verb), onConfirm = { - withApi { + withBGApi { val conf = NetCfg.defaults chatModel.controller.apiSetNetworkConfig(conf) chatModel.controller.setNetCfg(conf) @@ -111,7 +111,7 @@ fun NetworkAndServersView( onionHosts.value = prevValue } ) { - withApi { + withBGApi { val newCfg = chatModel.controller.getNetCfg().withOnionHosts(it) val res = chatModel.controller.apiSetNetworkConfig(newCfg) if (res) { @@ -136,7 +136,7 @@ fun NetworkAndServersView( startsWith, onDismiss = { sessionMode.value = prevValue } ) { - withApi { + withBGApi { val newCfg = chatModel.controller.getNetCfg().copy(sessionMode = it) val res = chatModel.controller.apiSetNetworkConfig(newCfg) if (res) { @@ -160,7 +160,7 @@ fun NetworkAndServersView( proxyPort: State<Int>, showModal: (@Composable (ChatModel) -> Unit) -> (() -> Unit), showSettingsModal: (@Composable (ChatModel) -> Unit) -> (() -> Unit), - showCustomModal: (@Composable (ChatModel, () -> Unit) -> Unit) -> (() -> Unit), + showCustomModal: (@Composable ModalData.(ChatModel, () -> Unit) -> Unit) -> (() -> Unit), toggleSocksProxy: (Boolean) -> Unit, useOnion: (OnionHosts) -> Unit, updateSessionMode: (TransportSessionMode) -> Unit, diff --git a/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/views/usersettings/Preferences.kt b/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/views/usersettings/Preferences.kt index c375fc5459..8b7ac68205 100644 --- a/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/views/usersettings/Preferences.kt +++ b/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/views/usersettings/Preferences.kt @@ -26,7 +26,7 @@ fun PreferencesView(m: ChatModel, user: User, close: () -> Unit,) { close() } fun savePrefs(afterSave: () -> Unit = {}) { - withApi { + withBGApi { val newProfile = user.profile.toProfile().copy(preferences = preferences.toPreferences()) val updated = m.controller.apiUpdateProfile(user.remoteHostId, newProfile) if (updated != null) { diff --git a/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/views/usersettings/PrivacySettings.kt b/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/views/usersettings/PrivacySettings.kt index 3d2b7b7fa5..76aa905b81 100644 --- a/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/views/usersettings/PrivacySettings.kt +++ b/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/views/usersettings/PrivacySettings.kt @@ -96,7 +96,7 @@ fun PrivacySettingsView( val currentUser = chatModel.currentUser.value if (currentUser != null) { fun setSendReceiptsContacts(enable: Boolean, clearOverrides: Boolean) { - withApi { + withLongRunningApi(slow = 30_000, deadlock = 60_000) { val mrs = UserMsgReceiptSettings(enable, clearOverrides) chatModel.controller.apiSetUserContactReceipts(currentUser, mrs) chatModel.controller.appPrefs.privacyDeliveryReceiptsSet.set(true) @@ -119,7 +119,7 @@ fun PrivacySettingsView( } fun setSendReceiptsGroups(enable: Boolean, clearOverrides: Boolean) { - withApi { + withLongRunningApi(slow = 30_000, deadlock = 60_000) { val mrs = UserMsgReceiptSettings(enable, clearOverrides) chatModel.controller.apiSetUserGroupReceipts(currentUser, mrs) chatModel.controller.appPrefs.privacyDeliveryReceiptsSet.set(true) @@ -383,7 +383,7 @@ fun SimplexLockView( } LAMode.PASSCODE -> { ModalManager.fullscreen.showCustomModal { close -> - Surface(Modifier.fillMaxSize(), color = MaterialTheme.colors.background) { + Surface(Modifier.fillMaxSize(), color = MaterialTheme.colors.background, contentColor = LocalContentColor.current) { SetAppPasscodeView( submit = { laLockDelay.set(30) @@ -427,8 +427,9 @@ fun SimplexLockView( when (laResult) { LAResult.Success -> { ModalManager.fullscreen.showCustomModal { close -> - Surface(Modifier.fillMaxSize(), color = MaterialTheme.colors.background) { + Surface(Modifier.fillMaxSize(), color = MaterialTheme.colors.background, contentColor = LocalContentColor.current) { SetAppPasscodeView( + reason = generalGetString(MR.strings.la_app_passcode), submit = { passcodeAlert(generalGetString(MR.strings.passcode_changed)) }, cancel = { @@ -450,9 +451,11 @@ fun SimplexLockView( when (laResult) { LAResult.Success -> { ModalManager.fullscreen.showCustomModal { close -> - Surface(Modifier.fillMaxSize(), color = MaterialTheme.colors.background) { + Surface(Modifier.fillMaxSize(), color = MaterialTheme.colors.background, contentColor = LocalContentColor.current) { SetAppPasscodeView( passcodeKeychain = ksSelfDestructPassword, + prohibitedPasscodeKeychain = ksAppPassword, + reason = generalGetString(MR.strings.self_destruct), submit = { selfDestructPasscodeAlert(generalGetString(MR.strings.self_destruct_passcode_changed)) }, cancel = { @@ -485,7 +488,7 @@ fun SimplexLockView( } LAMode.PASSCODE -> { ModalManager.fullscreen.showCustomModal { close -> - Surface(Modifier.fillMaxSize(), color = MaterialTheme.colors.background) { + Surface(Modifier.fillMaxSize(), color = MaterialTheme.colors.background, contentColor = LocalContentColor.current) { SetAppPasscodeView( submit = { laLockDelay.set(30) @@ -553,7 +556,7 @@ fun SimplexLockView( fontSize = 16.sp, modifier = Modifier.padding(bottom = DEFAULT_PADDING_HALF) ) - ProfileNameField(selfDestructDisplayName, "", ::isValidDisplayName) + ProfileNameField(selfDestructDisplayName, "", { isValidDisplayName(it.trim()) }) LaunchedEffect(selfDestructDisplayName.value) { val new = selfDestructDisplayName.value if (isValidDisplayName(new) && selfDestructDisplayNamePref.get() != new) { @@ -596,9 +599,9 @@ private fun EnableSelfDestruct( selfDestruct: SharedPreference<Boolean>, close: () -> Unit ) { - Surface(Modifier.fillMaxSize(), color = MaterialTheme.colors.background) { + Surface(Modifier.fillMaxSize(), color = MaterialTheme.colors.background, contentColor = LocalContentColor.current) { SetAppPasscodeView( - passcodeKeychain = ksSelfDestructPassword, title = generalGetString(MR.strings.set_passcode), reason = generalGetString(MR.strings.enabled_self_destruct_passcode), + passcodeKeychain = ksSelfDestructPassword, prohibitedPasscodeKeychain = ksAppPassword, title = generalGetString(MR.strings.set_passcode), reason = generalGetString(MR.strings.enabled_self_destruct_passcode), submit = { selfDestruct.set(true) selfDestructPasscodeAlert(generalGetString(MR.strings.self_destruct_passcode_enabled)) diff --git a/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/views/usersettings/ProtocolServerView.kt b/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/views/usersettings/ProtocolServerView.kt index 4e8da36a7e..cb3b16b227 100644 --- a/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/views/usersettings/ProtocolServerView.kt +++ b/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/views/usersettings/ProtocolServerView.kt @@ -28,21 +28,19 @@ import chat.simplex.common.views.helpers.* import chat.simplex.common.views.newchat.QRCode import chat.simplex.common.model.ChatModel import chat.simplex.res.MR +import kotlinx.coroutines.* import kotlinx.coroutines.flow.distinctUntilChanged -import kotlinx.coroutines.isActive -import kotlinx.coroutines.launch @Composable fun ProtocolServerView(m: ChatModel, server: ServerCfg, serverProtocol: ServerProtocol, onUpdate: (ServerCfg) -> Unit, onDelete: () -> Unit) { var testing by remember { mutableStateOf(false) } - val scope = rememberCoroutineScope() ProtocolServerLayout( testing, server, serverProtocol, testServer = { testing = true - scope.launch { + withLongRunningApi { val res = testServerConnection(server, m) if (isActive) { onUpdate(res.first) @@ -160,7 +158,7 @@ private fun CustomServer( if (valid.value) { SectionDividerSpaced() SectionView(stringResource(MR.strings.smp_servers_add_to_another_device).uppercase()) { - QRCode(serverAddress.value, Modifier.aspectRatio(1f).padding(horizontal = DEFAULT_PADDING)) + QRCode(serverAddress.value) } } } diff --git a/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/views/usersettings/ProtocolServersView.kt b/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/views/usersettings/ProtocolServersView.kt index 66dde9f96c..e1668ab9ad 100644 --- a/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/views/usersettings/ProtocolServersView.kt +++ b/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/views/usersettings/ProtocolServersView.kt @@ -23,12 +23,10 @@ import chat.simplex.common.model.ServerAddress.Companion.parseServerAddress import chat.simplex.common.views.helpers.* import chat.simplex.common.model.* import chat.simplex.common.platform.appPlatform -import chat.simplex.common.views.usersettings.ScanProtocolServer import chat.simplex.res.MR -import kotlinx.coroutines.launch @Composable -fun ProtocolServersView(m: ChatModel, rhId: Long?, serverProtocol: ServerProtocol, close: () -> Unit) { +fun ModalData.ProtocolServersView(m: ChatModel, rhId: Long?, serverProtocol: ServerProtocol, close: () -> Unit) { var presetServers by remember(rhId) { mutableStateOf(emptyList<String>()) } var servers by remember(rhId) { mutableStateOf(m.userSMPServersUnsaved.value ?: emptyList()) @@ -56,16 +54,18 @@ fun ProtocolServersView(m: ChatModel, rhId: Long?, serverProtocol: ServerProtoco } LaunchedEffect(rhId) { - val res = m.controller.getUserProtoServers(rhId, serverProtocol) - if (res != null) { - currServers.value = res.protoServers - presetServers = res.presetServers - if (servers.isEmpty()) { - servers = currServers.value + withApi { + val res = m.controller.getUserProtoServers(rhId, serverProtocol) + if (res != null) { + currServers.value = res.protoServers + presetServers = res.presetServers + if (servers.isEmpty()) { + servers = currServers.value + } } } } - + val testServersJob = CancellableOnGoneJob() fun showServer(server: ServerCfg) { ModalManager.start.showModalCloseable(true) { close -> var old by remember { mutableStateOf(server) } @@ -91,7 +91,6 @@ fun ProtocolServersView(m: ChatModel, rhId: Long?, serverProtocol: ServerProtoco }) } } - val scope = rememberCoroutineScope() ModalView( close = { if (saveDisabled.value) close() @@ -148,7 +147,7 @@ fun ProtocolServersView(m: ChatModel, rhId: Long?, serverProtocol: ServerProtoco ) }, testServers = { - scope.launch { + testServersJob.value = withLongRunningApi { testServers(testing, servers, m) { servers = it m.userSMPServersUnsaved.value = servers @@ -338,6 +337,7 @@ private suspend fun runServersTest(servers: List<ServerCfg>, m: ChatModel, onUpd val updatedServers = ArrayList<ServerCfg>(servers) for ((index, server) in servers.withIndex()) { if (server.enabled) { + interruptIfCancelled() val (updatedServer, f) = testServerConnection(server, m) updatedServers.removeAt(index) updatedServers.add(index, updatedServer) @@ -352,7 +352,7 @@ private suspend fun runServersTest(servers: List<ServerCfg>, m: ChatModel, onUpd } private fun saveServers(rhId: Long?, protocol: ServerProtocol, currServers: MutableState<List<ServerCfg>>, servers: List<ServerCfg>, m: ChatModel, afterSave: () -> Unit = {}) { - withApi { + withBGApi { if (m.controller.setUserProtoServers(rhId, protocol, servers)) { currServers.value = servers m.userSMPServersUnsaved.value = null diff --git a/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/views/usersettings/RTCServers.kt b/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/views/usersettings/RTCServers.kt index 7cb30440d3..50bed458cc 100644 --- a/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/views/usersettings/RTCServers.kt +++ b/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/views/usersettings/RTCServers.kt @@ -155,7 +155,8 @@ fun RTCServersLayout( .height(160.dp) .fillMaxWidth(), shape = RoundedCornerShape(10.dp), - border = BorderStroke(1.dp, MaterialTheme.colors.secondaryVariant) + border = BorderStroke(1.dp, MaterialTheme.colors.secondaryVariant), + contentColor = LocalContentColor.current ) { SelectionContainer( Modifier.verticalScroll(rememberScrollState()) diff --git a/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/views/usersettings/ScanProtocolServer.kt b/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/views/usersettings/ScanProtocolServer.kt index 77cb0ead13..502b579d64 100644 --- a/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/views/usersettings/ScanProtocolServer.kt +++ b/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/views/usersettings/ScanProtocolServer.kt @@ -20,25 +20,17 @@ fun ScanProtocolServerLayout(rhId: Long?, onNext: (ServerCfg) -> Unit) { Column( Modifier .fillMaxSize() - .padding(horizontal = DEFAULT_PADDING) ) { - AppBarTitle(stringResource(MR.strings.smp_servers_scan_qr), withPadding = false) - Box( - Modifier - .fillMaxWidth() - .aspectRatio(ratio = 1F) - .padding(bottom = 12.dp) - ) { - QRCodeScanner { text -> - val res = parseServerAddress(text) - if (res != null) { - onNext(ServerCfg(remoteHostId = rhId, text, false, null, true)) - } else { - AlertManager.shared.showAlertMsg( - title = generalGetString(MR.strings.smp_servers_invalid_address), - text = generalGetString(MR.strings.smp_servers_check_address) - ) - } + AppBarTitle(stringResource(MR.strings.smp_servers_scan_qr)) + QRCodeScanner { text -> + val res = parseServerAddress(text) + if (res != null) { + onNext(ServerCfg(remoteHostId = rhId, text, false, null, true)) + } else { + AlertManager.shared.showAlertMsg( + title = generalGetString(MR.strings.smp_servers_invalid_address), + text = generalGetString(MR.strings.smp_servers_check_address) + ) } } } diff --git a/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/views/usersettings/SetDeliveryReceiptsView.kt b/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/views/usersettings/SetDeliveryReceiptsView.kt index b75f522686..c18fd3f6f6 100644 --- a/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/views/usersettings/SetDeliveryReceiptsView.kt +++ b/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/views/usersettings/SetDeliveryReceiptsView.kt @@ -24,7 +24,7 @@ fun SetDeliveryReceiptsView(m: ChatModel) { enableReceipts = { val currentUser = m.currentUser.value if (currentUser != null) { - withApi { + withBGApi { try { m.controller.apiSetAllContactReceipts(currentUser.remoteHostId, enable = true) m.currentUser.value = currentUser.copy(sendRcptsContacts = true) diff --git a/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/views/usersettings/SettingsView.kt b/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/views/usersettings/SettingsView.kt index 0f37fb1979..d92f2f0f13 100644 --- a/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/views/usersettings/SettingsView.kt +++ b/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/views/usersettings/SettingsView.kt @@ -33,7 +33,7 @@ import chat.simplex.common.views.onboarding.WhatsNewView import chat.simplex.common.views.remote.ConnectDesktopView import chat.simplex.common.views.remote.ConnectMobileView import chat.simplex.res.MR -import kotlinx.coroutines.launch +import kotlinx.coroutines.* @Composable fun SettingsView(chatModel: ChatModel, setPerformLA: (Boolean) -> Unit, drawerState: DrawerState) { @@ -62,7 +62,7 @@ fun SettingsView(chatModel: ChatModel, setPerformLA: (Boolean) -> Unit, drawerSt }, showCustomModal = { modalView -> { ModalManager.start.showCustomModal { close -> modalView(chatModel, close) } } }, showVersion = { - withApi { + withBGApi { val info = chatModel.controller.apiGetVersion() if (info != null) { ModalManager.start.showModal { VersionInfoView(info) } @@ -89,7 +89,7 @@ fun SettingsLayout( showModal: (@Composable (ChatModel) -> Unit) -> (() -> Unit), showSettingsModal: (@Composable (ChatModel) -> Unit) -> (() -> Unit), showSettingsModalWithSearch: (@Composable (ChatModel, MutableState<String>) -> Unit) -> Unit, - showCustomModal: (@Composable (ChatModel, () -> Unit) -> Unit) -> (() -> Unit), + showCustomModal: (@Composable ModalData.(ChatModel, () -> Unit) -> Unit) -> (() -> Unit), showVersion: () -> Unit, withAuth: (title: String, desc: String, block: () -> Unit) -> Unit, drawerState: DrawerState, @@ -119,7 +119,7 @@ fun SettingsLayout( SectionItemView(showCustomModal { chatModel, close -> UserProfileView(chatModel, close) }, 80.dp, padding = PaddingValues(start = 16.dp, end = DEFAULT_PADDING), disabled = stopped) { ProfilePreview(profile, stopped = stopped) } - SettingsActionItem(painterResource(MR.images.ic_manage_accounts), stringResource(MR.strings.your_chat_profiles), { withAuth(generalGetString(MR.strings.auth_open_chat_profiles), generalGetString(MR.strings.auth_log_in_using_credential)) { showSettingsModalWithSearch { it, search -> UserProfilesView(it, search, profileHidden) } } }, disabled = stopped, extraPadding = true) + SettingsActionItem(painterResource(MR.images.ic_manage_accounts), stringResource(MR.strings.your_chat_profiles), { withAuth(generalGetString(MR.strings.auth_open_chat_profiles), generalGetString(MR.strings.auth_log_in_using_credential)) { showSettingsModalWithSearch { it, search -> UserProfilesView(it, search, profileHidden, drawerState) } } }, disabled = stopped, extraPadding = true) SettingsActionItem(painterResource(MR.images.ic_qr_code), stringResource(MR.strings.your_simplex_contact_address), showCustomModal { it, close -> UserAddressView(it, shareViaProfile = it.currentUser.value!!.addressShared, close = close) }, disabled = stopped, extraPadding = true) ChatPreferencesItem(showCustomModal, stopped = stopped) } else if (chatModel.localUserCreated.value == false) { @@ -186,7 +186,7 @@ fun SettingsLayout( @Composable expect fun SettingsSectionApp( showSettingsModal: (@Composable (ChatModel) -> Unit) -> (() -> Unit), - showCustomModal: (@Composable (ChatModel, () -> Unit) -> Unit) -> (() -> Unit), + showCustomModal: (@Composable ModalData.(ChatModel, () -> Unit) -> Unit) -> (() -> Unit), showVersion: () -> Unit, withAuth: (title: String, desc: String, block: () -> Unit) -> Unit ) @@ -218,16 +218,14 @@ expect fun SettingsSectionApp( } } -@Composable fun ChatPreferencesItem(showCustomModal: ((@Composable (ChatModel, () -> Unit) -> Unit) -> (() -> Unit)), stopped: Boolean) { +@Composable fun ChatPreferencesItem(showCustomModal: ((@Composable ModalData.(ChatModel, () -> Unit) -> Unit) -> (() -> Unit)), stopped: Boolean) { SettingsActionItem( painterResource(MR.images.ic_toggle_on), stringResource(MR.strings.chat_preferences), click = if (stopped) null else ({ - withApi { - showCustomModal { m, close -> - PreferencesView(m, m.currentUser.value ?: return@showCustomModal, close) - }() - } + showCustomModal { m, close -> + PreferencesView(m, m.currentUser.value ?: return@showCustomModal, close) + }() }), disabled = stopped, extraPadding = true diff --git a/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/views/usersettings/UserAddressView.kt b/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/views/usersettings/UserAddressView.kt index 915120d81d..ffaec8eb04 100644 --- a/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/views/usersettings/UserAddressView.kt +++ b/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/views/usersettings/UserAddressView.kt @@ -70,7 +70,7 @@ fun UserAddressView( shareViaProfile, onCloseHandler, createAddress = { - withApi { + withBGApi { progressIndicator = true val connReqContact = chatModel.controller.apiCreateUserAddress(user?.value?.remoteHostId) if (connReqContact != null) { @@ -116,7 +116,7 @@ fun UserAddressView( confirmText = generalGetString(MR.strings.delete_verb), onConfirm = { progressIndicator = true - withApi { + withBGApi { val u = chatModel.controller.apiDeleteUserAddress(user?.value?.remoteHostId) if (u != null) { chatModel.userAddress.value = null @@ -155,7 +155,7 @@ fun UserAddressView( contentAlignment = Alignment.Center ) { if (userAddress.value != null) { - Surface(Modifier.size(50.dp), color = MaterialTheme.colors.background.copy(0.9f), shape = RoundedCornerShape(50)){} + Surface(Modifier.size(50.dp), color = MaterialTheme.colors.background.copy(0.9f), contentColor = LocalContentColor.current, shape = RoundedCornerShape(50)){} } CircularProgressIndicator( Modifier @@ -207,7 +207,7 @@ private fun UserAddressLayout( val autoAcceptState = remember { mutableStateOf(AutoAcceptState(userAddress)) } val autoAcceptStateSaved = remember { mutableStateOf(autoAcceptState.value) } SectionView(stringResource(MR.strings.address_section_title).uppercase()) { - SimpleXLinkQRCode(userAddress.connReqContact, Modifier.padding(horizontal = DEFAULT_PADDING, vertical = DEFAULT_PADDING_HALF).aspectRatio(1f)) + SimpleXLinkQRCode(userAddress.connReqContact) ShareAddressButton { share(simplexChatLink(userAddress.connReqContact)) } ShareViaEmailButton { sendEmail(userAddress) } ShareWithContactsButton(shareViaProfile, setProfileAddress) diff --git a/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/views/usersettings/UserProfileView.kt b/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/views/usersettings/UserProfileView.kt index bf7c4ac802..1f5177d08b 100644 --- a/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/views/usersettings/UserProfileView.kt +++ b/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/views/usersettings/UserProfileView.kt @@ -40,7 +40,7 @@ fun UserProfileView(chatModel: ChatModel, close: () -> Unit) { profile = profile, close, saveProfile = { displayName, fullName, image -> - withApi { + withBGApi { val updated = chatModel.controller.apiUpdateProfile(user.remoteHostId, profile.copy(displayName = displayName.trim(), fullName = fullName, image = image)) if (updated != null) { val (newProfile, _) = updated diff --git a/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/views/usersettings/UserProfilesView.kt b/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/views/usersettings/UserProfilesView.kt index 390f1cac9b..1beccd516c 100644 --- a/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/views/usersettings/UserProfilesView.kt +++ b/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/views/usersettings/UserProfilesView.kt @@ -27,18 +27,20 @@ import chat.simplex.common.ui.theme.* import chat.simplex.common.views.chat.item.ItemAction import chat.simplex.common.views.chatlist.UserProfilePickerItem import chat.simplex.common.views.chatlist.UserProfileRow -import chat.simplex.common.views.database.PassphraseField import chat.simplex.common.views.helpers.* import chat.simplex.common.views.CreateProfile +import chat.simplex.common.views.database.* +import chat.simplex.common.views.onboarding.OnboardingStage import chat.simplex.res.MR import dev.icerock.moko.resources.StringResource -import kotlinx.coroutines.delay +import kotlinx.coroutines.* @Composable -fun UserProfilesView(m: ChatModel, search: MutableState<String>, profileHidden: MutableState<Boolean>) { +fun UserProfilesView(m: ChatModel, search: MutableState<String>, profileHidden: MutableState<Boolean>, drawerState: DrawerState) { val searchTextOrPassword = rememberSaveable { search } val users by remember { derivedStateOf { m.users.map { it.user } } } val filteredUsers by remember { derivedStateOf { filteredUsers(m, searchTextOrPassword.value) } } + val scope = rememberCoroutineScope() UserProfilesLayout( users = users, filteredUsers = filteredUsers, @@ -49,6 +51,12 @@ fun UserProfilesView(m: ChatModel, search: MutableState<String>, profileHidden: addUser = { ModalManager.center.showModalCloseable { close -> CreateProfile(m, close) + if (appPlatform.isDesktop) { + // Hide settings to allow clicks to pass through to CreateProfile view + DisposableEffectOnGone(always = { scope.launch { drawerState.close() } }) { + // Show settings again to allow intercept clicks to close modals after profile creation finishes + scope.launch(NonCancellable) { drawerState.open() } } + } } }, activateUser = { user -> @@ -63,45 +71,34 @@ fun UserProfilesView(m: ChatModel, search: MutableState<String>, profileHidden: } }, removeUser = { user -> - if (m.users.size > 1 && (user.hidden || visibleUsersCount(m) > 1)) { - val text = buildAnnotatedString { - append(generalGetString(MR.strings.users_delete_all_chats_deleted) + "\n\n" + generalGetString(MR.strings.users_delete_profile_for) + " ") - withStyle(SpanStyle(fontWeight = FontWeight.Bold)) { - append(user.displayName) - } - append(":") + val text = buildAnnotatedString { + append(generalGetString(MR.strings.users_delete_all_chats_deleted) + "\n\n" + generalGetString(MR.strings.users_delete_profile_for) + " ") + withStyle(SpanStyle(fontWeight = FontWeight.Bold)) { + append(user.displayName) } - AlertManager.shared.showAlertDialogButtonsColumn( - title = generalGetString(MR.strings.users_delete_question), - text = text, - buttons = { - Column { - SectionItemView({ - AlertManager.shared.hideAlert() - removeUser(m, user, users, true, searchTextOrPassword.value.trim()) - }) { - Text(stringResource(MR.strings.users_delete_with_connections), Modifier.fillMaxWidth(), textAlign = TextAlign.Center, color = Color.Red) - } - SectionItemView({ - AlertManager.shared.hideAlert() - removeUser(m, user, users, false, searchTextOrPassword.value.trim()) - } - ) { - Text(stringResource(MR.strings.users_delete_data_only), Modifier.fillMaxWidth(), textAlign = TextAlign.Center, color = Color.Red) - } + append(":") + } + AlertManager.shared.showAlertDialogButtonsColumn( + title = generalGetString(MR.strings.users_delete_question), + text = text, + buttons = { + Column { + SectionItemView({ + AlertManager.shared.hideAlert() + removeUser(m, user, users, true, searchTextOrPassword.value.trim()) + }) { + Text(stringResource(MR.strings.users_delete_with_connections), Modifier.fillMaxWidth(), textAlign = TextAlign.Center, color = Color.Red) + } + SectionItemView({ + AlertManager.shared.hideAlert() + removeUser(m, user, users, false, searchTextOrPassword.value.trim()) + } + ) { + Text(stringResource(MR.strings.users_delete_data_only), Modifier.fillMaxWidth(), textAlign = TextAlign.Center, color = Color.Red) } } - ) - } else { - AlertManager.shared.showAlertMsg( - title = generalGetString(MR.strings.cant_delete_user_profile), - text = if (m.users.size > 1) { - generalGetString(MR.strings.should_be_at_least_one_visible_profile) - } else { - generalGetString(MR.strings.should_be_at_least_one_profile) - } - ) - } + } + ) }, unhideUser = { user -> if (passwordEntryRequired(user, searchTextOrPassword.value)) { @@ -178,7 +175,7 @@ private fun UserProfilesLayout( SectionView { for (user in filteredUsers) { - UserView(user, users, visibleUsersCount, activateUser, removeUser, unhideUser, muteUser, unmuteUser, showHiddenProfile) + UserView(user, visibleUsersCount, activateUser, removeUser, unhideUser, muteUser, unmuteUser, showHiddenProfile) SectionDivider() } if (searchTextOrPassword.value.trim().isEmpty()) { @@ -210,7 +207,6 @@ private fun UserProfilesLayout( @Composable private fun UserView( user: User, - users: List<User>, visibleUsersCount: Int, activateUser: (User) -> Unit, removeUser: (User) -> Unit, @@ -220,7 +216,7 @@ private fun UserView( showHiddenProfile: (User) -> Unit, ) { val showMenu = remember { mutableStateOf(false) } - UserProfilePickerItem(user, onLongClick = { if (users.size > 1) showMenu.value = true }) { + UserProfilePickerItem(user, onLongClick = { showMenu.value = true }) { activateUser(user) } Box(Modifier.padding(horizontal = DEFAULT_PADDING)) { @@ -350,22 +346,28 @@ private fun removeUser(m: ChatModel, user: User, users: List<User>, delSMPQueues } private suspend fun doRemoveUser(m: ChatModel, user: User, users: List<User>, delSMPQueues: Boolean, viewPwd: String?) { - if (users.size < 2) return - - suspend fun deleteUser(user: User) { - m.controller.apiDeleteUser(user, delSMPQueues, viewPwd) - m.removeUser(user) - } try { - if (user.activeUser) { - val newActive = users.firstOrNull { u -> !u.activeUser && !u.hidden } - if (newActive != null) { - m.controller.changeActiveUser_(newActive.remoteHostId, newActive.userId, null) - deleteUser(user.copy(activeUser = false)) + when { + user.activeUser -> { + val newActive = users.firstOrNull { u -> !u.activeUser && !u.hidden } + if (newActive != null) { + m.controller.changeActiveUser_(user.remoteHostId, newActive.userId, null) + m.controller.apiDeleteUser(user, delSMPQueues, viewPwd) + } else { + // Deleting the last visible user while having hidden one(s) + m.controller.apiDeleteUser(user, delSMPQueues, viewPwd) + m.controller.changeActiveUser_(user.remoteHostId, null, null) + if (appPlatform.isAndroid) { + controller.appPrefs.onboardingStage.set(OnboardingStage.Step1_SimpleXInfo) + ModalManager.closeAllModalsEverywhere() + } + } + } + else -> { + m.controller.apiDeleteUser(user, delSMPQueues, viewPwd) } - } else { - deleteUser(user) } + m.removeUser(user) } catch (e: Exception) { AlertManager.shared.showAlertMsg(generalGetString(MR.strings.error_deleting_user), e.stackTraceToString()) } diff --git a/apps/multiplatform/common/src/commonMain/resources/MR/ar/strings.xml b/apps/multiplatform/common/src/commonMain/resources/MR/ar/strings.xml index d16892096c..94a8ab76b4 100644 --- a/apps/multiplatform/common/src/commonMain/resources/MR/ar/strings.xml +++ b/apps/multiplatform/common/src/commonMain/resources/MR/ar/strings.xml @@ -22,27 +22,27 @@ <string name="the_messaging_and_app_platform_protecting_your_privacy_and_security">منصة الرسائل والتطبيقات تحمي خصوصيتك وأمنك.</string> <string name="profile_is_only_shared_with_your_contacts">يتم مشاركة ملف التعريف مع جهات اتصالك فقط.</string> <string name="member_role_will_be_changed_with_notification">سيتم تغيير الدور إلى \"%s\". سيتم إبلاغ كل فرد في المجموعة.</string> - <string name="member_role_will_be_changed_with_invitation">سيتم تغيير الدور إلى \"%s\". سيتلقى العضو دعوة جديدة.</string> + <string name="member_role_will_be_changed_with_invitation">سيتم تغيير الدور إلى \"%s\". سيستلم العضو دعوة جديدة.</string> <string name="smp_servers_per_user">خوادم الاتصالات الجديدة لملف تعريف الدردشة الحالي الخاص بك</string> <string name="switch_receiving_address_desc">سيتم تغيير عنوان الاستلام إلى خادم مختلف. سيتم إكمال تغيير العنوان بعد اتصال المرسل بالإنترنت.</string> - <string name="this_link_is_not_a_valid_connection_link">هذا الارتباط ليس ارتباط اتصال صالح!</string> + <string name="this_link_is_not_a_valid_connection_link">هذا الرابط ليس رابط اتصال صالح!</string> <string name="allow_verb">يسمح</string> - <string name="smp_servers_preset_add">أضف خوادم محددة مسبقًا</string> - <string name="smp_servers_add_to_another_device">أضف إلى جهاز آخر</string> + <string name="smp_servers_preset_add">أضِف خوادم محدّدة مسبقًا</string> + <string name="smp_servers_add_to_another_device">أضِف إلى جهاز آخر</string> <string name="users_delete_all_chats_deleted">سيتم حذف جميع الدردشات والرسائل - لا يمكن التراجع عن هذا!</string> <string name="network_enable_socks_info">الوصول إلى الخوادم عبر بروكسي SOCKS على المنفذ %d؟ يجب بدء تشغيل الوكيل قبل تمكين هذا الخيار.</string> - <string name="smp_servers_add">إضافة خادم …</string> + <string name="smp_servers_add">أضِف خادم…</string> <string name="network_settings">إعدادات الشبكة المتقدمة</string> <string name="all_group_members_will_remain_connected">سيبقى جميع أعضاء المجموعة على اتصال.</string> <string name="allow_disappearing_messages_only_if">السماح باختفاء الرسائل فقط إذا سمحت جهة اتصالك بذلك.</string> - <string name="allow_irreversible_message_deletion_only_if">السماح بحذف الرسائل بشكل لا رجوع فيه فقط إذا سمحت لك جهة الاتصال بذلك.</string> - <string name="group_member_role_admin">مسؤل</string> - <string name="users_add">إضافة ملف التعريف</string> + <string name="allow_irreversible_message_deletion_only_if">السماح بحذف الرسائل بشكل لا رجوع فيه فقط إذا سمحت لك جهة الاتصال بذلك. (24 ساعة)</string> + <string name="group_member_role_admin">المشرف</string> + <string name="users_add">أضِف ملف التعريف</string> <string name="allow_direct_messages">السماح بإرسال رسائل مباشرة إلى الأعضاء.</string> <string name="accept_contact_incognito_button">قبول التخفي</string> - <string name="button_add_welcome_message">أضف رسالة ترحيب</string> + <string name="button_add_welcome_message">أضِف رسالة ترحيب</string> <string name="v4_3_improved_server_configuration_desc">أضف الخوادم عن طريق مسح رموز QR.</string> - <string name="v4_2_group_links_desc">يمكن للمسؤولين إنشاء روابط للانضمام إلى المجموعات.</string> + <string name="v4_2_group_links_desc">يمكّن للمشرفين إنشاء روابط للانضمام إلى المجموعات.</string> <string name="accept_connection_request__question">قبول طلب الاتصال؟</string> <string name="clear_chat_warning">سيتم حذف جميع الرسائل - لا يمكن التراجع عن هذا! سيتم حذف الرسائل فقط من أجلك.</string> <string name="callstatus_accepted">مكالمة مقبولة</string> @@ -65,13 +65,13 @@ <string name="allow_voice_messages_only_if">اسمح بالرسائل الصوتية فقط إذا سمحت جهة اتصالك بذلك.</string> <string name="v5_0_app_passcode">رمز مرور التطبيق</string> <string name="notifications_mode_service">دائِماً مُتاح</string> - <string name="notifications_mode_off_desc">يمكن للتطبيق تلقي الإشعارات فقط عند تشغيله ، ولن يتم بدء تشغيل أي خدمة في الخلفية</string> + <string name="notifications_mode_off_desc">يمكن للتطبيق استلام الإشعارات فقط عند تشغيله، ولن يتم بدء تشغيل أي خدمة في الخلفية</string> <string name="allow_voice_messages_question">السماح بالرسائل الصوتية؟</string> <string name="all_your_contacts_will_remain_connected">ستبقى جميع جهات الاتصال الخاصة بك متصلة.</string> <string name="always_use_relay">استخدم التتابع دائمًا</string> <string name="full_backup">النسخ الاحتياطي لبيانات التطبيق</string> <string name="all_app_data_will_be_cleared">حُذفت جميع بيانات التطبيق.</string> - <string name="allow_to_delete_messages">السماح بحذف الرسائل المرسلة بشكل لا رجعة فيه.</string> + <string name="allow_to_delete_messages">السماح بحذف الرسائل المرسلة بشكل لا رجعة فيه. (24 ساعة)</string> <string name="allow_your_contacts_to_send_voice_messages">اسمح لجهات اتصالك بإرسال رسائل صوتية.</string> <string name="learn_more_about_address">حول عنوان SimpleX</string> <string name="app_version_code">بناء التطبيق: %s</string> @@ -80,13 +80,13 @@ <string name="all_your_contacts_will_remain_connected_update_sent">ستبقى جميع جهات الاتصال الخاصة بك متصلة. سيتم إرسال تحديث الملف الشخصي إلى جهات الاتصال الخاصة بك.</string> <string name="settings_section_title_icon">رمز التطبيق</string> <string name="address_section_title">عنوان</string> - <string name="allow_your_contacts_irreversibly_delete">اسمح لجهات اتصالك بحذف الرسائل المرسلة بشكل لا رجعة فيه.</string> + <string name="allow_your_contacts_irreversibly_delete">اسمح لجهات اتصالك بحذف الرسائل المرسلة بشكل لا رجعة فيه. (24 ساعة)</string> <string name="auth_unavailable">المصادقة غير متاحة</string> <string name="back">رجوع</string> <string name="invite_prohibited">لا يمكن دعوة جهة اتصال!</string> <string name="icon_descr_cancel_image_preview">إلغاء معاينة الصورة</string> <string name="use_camera_button">الكاميرا</string> - <string name="icon_descr_cancel_link_preview">إلغاء معاينة الارتباط</string> + <string name="icon_descr_cancel_link_preview">إلغاء معاينة الروابط</string> <string name="network_session_mode_user_description"><![CDATA[سيتم استخدام اتصال TCP منفصل (وبيانات اعتماد SOCKS) <b> لكل ملف تعريف دردشة لديك في التطبيق </b>.]]></string> <string name="feature_cancelled_item">ألغيت %s</string> <string name="one_time_link_short">رابط لمرة واحدة</string> @@ -96,11 +96,11 @@ <string name="both_you_and_your_contact_can_add_message_reactions">يمكنك أنت وجهة اتصالك إضافة ردود فعل الرسائل.</string> <string name="both_you_and_your_contact_can_send_disappearing">يمكنك أنت وجهة اتصالك إرسال رسائل تختفي.</string> <string name="icon_descr_call_progress">مكالمتك تحت الإجراء</string> - <string name="cannot_receive_file">لا يمكن استقبال الملف</string> + <string name="cannot_receive_file">لا يمكّن استلام الملف</string> <string name="onboarding_notifications_mode_periodic_desc"><![CDATA[<b> جيد للبطارية </b>. خدمة الخلفية تتحقق من الرسائل كل 10 دقائق. قد تفوتك مكالمات أو رسائل عاجلة.]]></string> <string name="bold_text">عريض</string> - <string name="audio_call_no_encryption">مكالمات الصوت (ليست مشفرة بين الطرفين)</string> - <string name="onboarding_notifications_mode_off_desc"><![CDATA[<b> الأفضل للبطارية </b>. ستتلقى إشعارات فقط عندما يكون التطبيق قيد التشغيل (لا توجد خدمة في الخلفية).]]></string> + <string name="audio_call_no_encryption">مكالمات الصوت (ليست مُعمّاة بين الطرفين)</string> + <string name="onboarding_notifications_mode_off_desc"><![CDATA[<b> الأفضل للبطارية </b>. ستستلم إشعارات فقط عندما يكون التطبيق قيد التشغيل (لا توجد خدمة في الخلفية).]]></string> <string name="onboarding_notifications_mode_service_desc"><![CDATA[<b> تستهلك المزيد من البطارية </b>! تعمل خدمة الخلفية دائمًا - تظهر الإشعارات بمجرد توفر الرسائل.]]></string> <string name="call_already_ended">انتهت المكالمة بالفعل!</string> <string name="alert_title_msg_bad_hash">تجزئة رسالة سيئة</string> @@ -115,7 +115,7 @@ <string name="it_can_disabled_via_settings_notifications_still_shown"><![CDATA[<b> يمكن تعطيله عبر الإعدادات</b> - سيستمر عرض الإشعارات أثناء تشغيل التطبيق.]]></string> <string name="settings_audio_video_calls">مكالمات الصوت والفيديو</string> <string name="impossible_to_recover_passphrase"><![CDATA[<b>يُرجى الملاحظة</b>: لن تتمكن من استعادة عبارة المرور أو تغييرها في حالة فقدها.]]></string> - <string name="both_you_and_your_contacts_can_delete">يمكنك أنت وجهة اتصالك حذف الرسائل المرسلة بشكل لا رجعة فيه.</string> + <string name="both_you_and_your_contacts_can_delete">يمكنك أنت وجهة اتصالك حذف الرسائل المرسلة بشكل لا رجعة فيه. (24 ساعة)</string> <string name="v4_2_auto_accept_contact_requests">قبول طلبات الاتصال تلقائيًا</string> <string name="la_auth_failed">فشلت المصادقة</string> <string name="la_authenticate">مصادقة</string> @@ -145,10 +145,7 @@ <string name="settings_section_title_calls">المكالمات</string> <string name="alert_title_cant_invite_contacts">لا يمكن دعوة جهات الاتصال!</string> <string name="rcv_conn_event_switch_queue_phase_completed">تم تغيير العنوان من أجلك</string> - <string name="cant_delete_user_profile">لا يمكن حذف ملف تعريف المستخدم!</string> <string name="icon_descr_video_asked_to_receive">طلب لاستلام الفيديو</string> - <string name="add_new_contact_to_create_one_time_QR_code"><![CDATA[<b> إضافة جهة اتصال جديدة </b>: لإنشاء رمز الاستجابة السريعة الخاص بك لمرة واحدة لجهة اتصالك.]]></string> - <string name="scan_QR_code_to_connect_to_contact_who_shows_QR_code"><![CDATA[<b> امسح رمز الاستجابة السريعة </b>: للاتصال بجهة الاتصال التي تعرض لك رمز الاستجابة السريعة.]]></string> <string name="callstatus_in_progress">مكالمتك تحت الإجراء</string> <string name="change_database_passphrase_question">تغيير عبارة مرور قاعدة البيانات؟</string> <string name="cannot_access_keychain">لا يمكن الوصول إلى Keystore لحفظ كلمة مرور قاعدة البيانات</string> @@ -173,8 +170,8 @@ <string name="copy_verb">نسخ</string> <string name="connect_via_link_verb">اتصل</string> <string name="server_connected">متصل</string> - <string name="connect_via_group_link">تواصل عبر رابط جماعي؟</string> - <string name="connect_via_invitation_link">تواصل عبر رابط دعوة؟</string> + <string name="connect_via_group_link">انضمام إلى المجموعة؟</string> + <string name="connect_via_invitation_link">اتصل عبر رابط لمرة واحدة؟</string> <string name="switch_receiving_address_question">تغيير عنوان الاستلام؟</string> <string name="copied">نٌسخت إلى الحافظة</string> <string name="clear_verb">مسح</string> @@ -182,8 +179,8 @@ <string name="create_address">إنشاء عنوان</string> <string name="settings_section_title_chats">الدردشات</string> <string name="confirm_new_passphrase">تأكيد عبارة المرور الجديدة…</string> - <string name="encrypt_database_question">تشفير قاعدة بيانات</string> - <string name="encrypted_database">قاعدة بيانات مشفرة</string> + <string name="encrypt_database_question">تعمية قاعدة البيانات؟</string> + <string name="encrypted_database">قاعدة البيانات مُعمّاة</string> <string name="rcv_group_event_changed_member_role">غيرت دور %s إلى %s</string> <string name="switch_receiving_address">تغيير عنوان الاستلام</string> <string name="failed_to_create_user_title">خطأ في إنشاء الملف الشخصي!</string> @@ -198,7 +195,6 @@ <string name="smp_server_test_compare_file">قارن الملف</string> <string name="icon_descr_server_status_error">خطأ</string> <string name="create_group">إنشاء مجموعة سرية</string> - <string name="create_one_time_link">إنشاء رابط دعوة لمرة واحدة</string> <string name="error_aborting_address_change">خطأ في إحباط تغيير العنوان</string> <string name="auth_enable_simplex_lock">تفعيل قفل SimpleX</string> <string name="auth_confirm_credential">تأكد من بيانات الاعتماد الخاصة بك</string> @@ -223,7 +219,7 @@ <string name="enable_lock">تفعيل القفل</string> <string name="confirm_passcode">تأكيد رمز المرور</string> <string name="error_deleting_database">خطأ في حذف قاعدة بيانات الدردشة</string> - <string name="error_encrypting_database">خطأ في تشفير قاعدة بيانات</string> + <string name="error_encrypting_database">خطأ في تعمية قاعدة البيانات</string> <string name="chat_is_stopped_indication">توقفت الدردشة</string> <string name="group_member_status_complete">مكتمل</string> <string name="group_member_status_announced">جاري الاتصال (أعلن)</string> @@ -234,30 +230,30 @@ <string name="v4_6_chinese_spanish_interface">الواجهة الصينية والاسبانية</string> <string name="clear_chat_menu_action">مسح</string> <string name="contact_wants_to_connect_via_call">%1$s يريد التواصل معك عبر</string> - <string name="snd_conn_event_switch_queue_phase_changing">تغيير العنوان…</string> - <string name="snd_conn_event_switch_queue_phase_changing_for_member">تغيير العنوان ل%s…</string> + <string name="snd_conn_event_switch_queue_phase_changing">جارِ تغيير العنوان…</string> + <string name="snd_conn_event_switch_queue_phase_changing_for_member">جارِ تغيير العنوان ل%s…</string> <string name="allow_to_send_files">السماح بإرسال الملفات والوسائط.</string> <string name="enter_welcome_message_optional">أدخل رسالة ترحيب… (اختياري)</string> - <string name="snd_conn_event_ratchet_sync_agreed">وافق التشفير ل%s</string> - <string name="snd_conn_event_ratchet_sync_allowed">سمح بإعادة التفاوض على التشفير ل%s</string> + <string name="snd_conn_event_ratchet_sync_agreed">وافق التعمية ل%s</string> + <string name="snd_conn_event_ratchet_sync_allowed">سمح بإعادة التفاوض على التعمية ل%s</string> <string name="error_accepting_contact_request">خطأ في قبول طلب جهة الاتصال</string> - <string name="status_contact_has_no_e2e_encryption">ليس لدى جهة الاتصال التشفير بين الطريفين</string> + <string name="status_contact_has_no_e2e_encryption">ليس لدى جهة الاتصال التعمية بين الطريفين</string> <string name="change_self_destruct_mode">تغيير وضع التدمير الذاتي</string> <string name="change_self_destruct_passcode">تغيير رمز المرور التدمير الذاتي</string> <string name="confirm_database_upgrades">تأكيد ترقيات قاعدة البيانات</string> <string name="chat_archive_header">أرشيف الدردشة</string> <string name="group_member_status_intro_invitation">الاتصال (دعوة مقدمة)</string> <string name="clear_contacts_selection_button">مسح</string> - <string name="error_creating_link_for_group">خطأ في إنشاء ارتباط المجموعة</string> + <string name="error_creating_link_for_group">خطأ في إنشاء رابط المجموعة</string> <string name="item_info_current">(حاضِر)</string> - <string name="network_option_enable_tcp_keep_alive">تمكين بقاء TCP على قيد الحياة</string> + <string name="network_option_enable_tcp_keep_alive">تفعيل أبقِ TCP على قيد الحياة</string> <string name="contact_connection_pending">جار الاتصال…</string> <string name="group_connection_pending">جار الاتصال…</string> <string name="connection_request_sent">أرسلت طلب الاتصال!</string> <string name="chat_database_deleted">حُذفت قاعدة بيانات الدردشة</string> <string name="chat_archive_section">أرشيف الدردشة</string> <string name="archive_created_on_ts">نشأ في %1$s</string> - <string name="rcv_conn_event_switch_queue_phase_changing">تغيير العنوان…</string> + <string name="rcv_conn_event_switch_queue_phase_changing">جارِ تغيير العنوان…</string> <string name="group_member_status_accepted">جار الاتصال (قُبِل)</string> <string name="icon_descr_contact_checked">فُحصت جهة الاتصال</string> <string name="group_info_section_title_num_members">%1$s أعضاء</string> @@ -276,7 +272,7 @@ <string name="chat_preferences">تفضيلات الدردشة</string> <string name="enter_correct_passphrase">أدخل عبارة المرور الصحيحة.</string> <string name="rcv_group_event_member_connected">متصل</string> - <string name="connect_via_contact_link">تواصل عبر رابط الاتصال؟</string> + <string name="connect_via_contact_link">اتصل عبر عنوان التواصل؟</string> <string name="error_deleting_link_for_group">خطأ في حذف رابط المجموعة</string> <string name="notifications_mode_periodic_desc">التحقق من الرسائل الجديدة كل 10 دقائق لمدة تصل إلى دقيقة واحدة</string> <string name="server_connecting">جار الاتصال</string> @@ -294,7 +290,7 @@ <string name="connection_local_display_name">الاتصال %1$d</string> <string name="display_name_connection_established">انشأت الاتصال</string> <string name="callstatus_connecting">مكالمة جارية…</string> - <string name="encrypt_database">تشفير</string> + <string name="encrypt_database">عَمِّ</string> <string name="enter_passphrase">أدخل عبارة المرور…</string> <string name="group_member_status_creator">المنشئ</string> <string name="error_adding_members">خطأ في إضافة الأعضاء</string> @@ -320,23 +316,23 @@ <string name="create_address_and_let_people_connect">أنشئ عنوانًا للسماح للأشخاص بالتواصل معك.</string> <string name="smp_servers_enter_manually">أدخل الخادم يدويًا</string> <string name="colored_text">ملون</string> - <string name="status_contact_has_e2e_encryption">لدى جهة الاتصال التشفير بين الطريفين</string> + <string name="status_contact_has_e2e_encryption">لدى جهة الاتصال التعمية بين الطريفين</string> <string name="create_profile_button">إنشاء</string> <string name="create_your_profile">إنشاء حسابك الشخصي</string> <string name="icon_descr_call_connecting">مكالمة جارية...</string> <string name="enable_self_destruct">تفعيل التدمير الذاتي</string> - <string name="conn_event_ratchet_sync_started">الموافقة على التشفير…</string> - <string name="snd_conn_event_ratchet_sync_started">الموافقة على التشفير لـ%s…</string> + <string name="conn_event_ratchet_sync_started">الموافقة على التعمية…</string> + <string name="snd_conn_event_ratchet_sync_started">الموافقة على التعمية لـ%s…</string> <string name="group_member_status_introduced">متصل (مقدم)</string> - <string name="conn_event_ratchet_sync_agreed">وافق التشفير</string> - <string name="conn_event_ratchet_sync_ok">التشفير نعم</string> - <string name="snd_conn_event_ratchet_sync_ok">التشفير نعم ل%s</string> - <string name="conn_event_ratchet_sync_allowed">سمح بإعادة التفاوض على التشفير</string> - <string name="conn_event_ratchet_sync_required">مطلوب إعادة التفاوض على التشفير</string> - <string name="snd_conn_event_ratchet_sync_required">مطلوب إعادة التفاوض على التشفير ل%s</string> + <string name="conn_event_ratchet_sync_agreed">وافق التعمية</string> + <string name="conn_event_ratchet_sync_ok">التعمية نعم</string> + <string name="snd_conn_event_ratchet_sync_ok">التعمية نعم ل%s</string> + <string name="conn_event_ratchet_sync_allowed">سمح بإعادة التفاوض على التعمية</string> + <string name="conn_event_ratchet_sync_required">مطلوب إعادة التفاوض على التعمية</string> + <string name="snd_conn_event_ratchet_sync_required">مطلوب إعادة التفاوض على التعمية ل%s</string> <string name="error_changing_message_deletion">خطأ في تغيير الإعداد</string> <string name="error_changing_role">خطأ في تغيير الدور</string> - <string name="alert_text_decryption_error_n_messages_failed_to_decrypt">%1$d فشل فك تشفير الرسائل.</string> + <string name="alert_text_decryption_error_n_messages_failed_to_decrypt">%1$d فشل فك تعمية الرسائل.</string> <string name="dark_theme">سمة داكنة</string> <string name="deleted_description">حُذِفت</string> <string name="database_passphrase_and_export">عبارة مرور قاعدة البيانات وتصديرها</string> @@ -348,7 +344,7 @@ <string name="delete_group_menu_action">حذف</string> <string name="delete_messages">حذف الرسائل</string> <string name="delete_messages_after">حذف الرسائل بعد</string> - <string name="database_encrypted">قاعدة بيانات مشفرة!</string> + <string name="database_encrypted">قاعدة البيانات مُعمّاة!</string> <string name="passphrase_is_different">تختلف عبارة مرور قاعدة البيانات عن تلك المحفوظة في Keystore.</string> <string name="database_error">خطأ في قاعدة البيانات</string> <string name="database_upgrade">ترقية قاعدة البيانات</string> @@ -364,8 +360,8 @@ <string name="delete_database">حذف قاعدة البيانات</string> <string name="delete_chat_profile_question">حذف ملف تعريف الدردشة؟</string> <string name="delete_files_and_media_for_all_users">حذف الملفات لجميع ملفات تعريف الدردشة</string> - <string name="encrypted_with_random_passphrase">قاعدة البيانات مشفرة باستخدام عبارة مرور عشوائية، يمكنك تغييرها.</string> - <string name="database_will_be_encrypted_and_passphrase_stored">سيتم تشفير قاعدة البيانات وتخزين عبارة المرور في Keystore.</string> + <string name="encrypted_with_random_passphrase">قاعدة البيانات مُعمّاة باستخدام عبارة مرور عشوائية، يمكنك تغييرها.</string> + <string name="database_will_be_encrypted_and_passphrase_stored">سيتم تعمية قاعدة البيانات وتخزين عبارة المرور في Keystore.</string> <string name="database_passphrase_is_required">عبارة مرور قاعدة البيانات مطلوبة لفتح الدردشة.</string> <string name="mtr_error_no_down_migration">إصدار قاعدة البيانات أحدث من التطبيق، ولكن لا يوجد ترحيل لأسفل ل%s</string> <string name="share_text_database_id">معرّف قاعدة البيانات: %d</string> @@ -374,13 +370,13 @@ <string name="full_deletion">حذف للجميع</string> <string name="custom_time_unit_days">أيام</string> <string name="delete_address">حذف العنوان</string> - <string name="database_passphrase_will_be_updated">سيتم تحديث عبارة مرور تشفير قاعدة البيانات.</string> + <string name="database_passphrase_will_be_updated">سيتم تحديث عبارة مرور تعمية قاعدة البيانات.</string> <string name="delete_archive">حذف الأرشيف</string> <string name="delete_link_question">حذف الرابط؟</string> <string name="database_downgrade">الرجوع إلى إصدار سابق من قاعدة البيانات</string> - <string name="set_password_to_export_desc">يتم تشفير قاعدة البيانات باستخدام عبارة مرور عشوائية. يرجى تغييره قبل التصدير.</string> + <string name="set_password_to_export_desc">قاعدة البيانات مُعمّاة باستخدام عبارة مرور عشوائية. يُرجى تغييره قبل التصدير.</string> <string name="ttl_day">%d يوم</string> - <string name="database_will_be_encrypted">سيتم تشفير قاعدة البيانات.</string> + <string name="database_will_be_encrypted">سيتم تعمية قاعدة البيانات.</string> <string name="delete_contact_menu_action">حذف</string> <string name="delete_files_and_media_question">حذف الملفات والوسائط؟</string> <string name="button_delete_contact">حذف جهة الاتصال</string> @@ -389,7 +385,7 @@ <string name="chat_preferences_default">الافتراضي %s</string> <string name="delete_pending_connection__question">حذف الاتصال قيد الانتظار؟</string> <string name="delete_chat_profile">حذف ملف تعريف الدردشة</string> - <string name="decryption_error">خطأ في فك التشفير</string> + <string name="decryption_error">خطأ في فك التعمية</string> <string name="delete_message__question">حذف الرسالة؟</string> <string name="developer_options">معرفات قاعدة البيانات وخيار عزل النقل.</string> <string name="delete_address__question">حذف العنوان؟</string> @@ -400,7 +396,7 @@ <string name="decentralized">لامركزي</string> <string name="database_passphrase">عبارة مرور قاعدة البيانات</string> <string name="current_passphrase">عبارة المرور الحالية…</string> - <string name="database_encryption_will_be_updated">سيتم تحديث عبارة مرور تشفير قاعدة البيانات وتخزينها في Keystore.</string> + <string name="database_encryption_will_be_updated">سيتم تحديث عبارة مرور تعمية قاعدة البيانات وتخزينها في Keystore.</string> <string name="info_row_database_id">معرّف قاعدة البيانات</string> <string name="info_row_deleted_at">حُذِفت في</string> <string name="ttl_d">%d يوم</string> @@ -414,7 +410,7 @@ <string name="desktop_scan_QR_code_from_app_via_scan_QR_code"><![CDATA[💻 سطح المكتب: امسح رمز الاستجابة السريعة (QR) المعروض من التطبيق، عبر <b>مسح رمز QR</b>.]]></string> <string name="delete_profile">حذف ملف التعريف</string> <string name="smp_servers_delete_server">حذف الخادم</string> - <string name="error_updating_link_for_group">خطأ في تحديث ارتباط المجموعة</string> + <string name="error_updating_link_for_group">خطأ في تحديث رابط المجموعة</string> <string name="simplex_link_mode_description">الوصف</string> <string name="icon_descr_expand_role">توسيع اختيار الدور</string> <string name="group_invitation_expired">انتهت صلاحية دعوة المجموعة</string> @@ -431,7 +427,7 @@ <string name="files_and_media_prohibited">الملفات والوسائط ممنوعة!</string> <string name="icon_descr_file">الملف</string> <string name="snd_group_event_group_profile_updated">حُدّث ملف تعريف المجموعة</string> - <string name="group_display_name_field">اسم عرض المجموعة:</string> + <string name="group_display_name_field">أدخل اسم المجموعة:</string> <string name="group_members_can_send_voice">يمكن لأعضاء المجموعة إرسال رسائل صوتية.</string> <string name="files_are_prohibited_in_group">الملفات والوسائط ممنوعة في هذه المجموعة.</string> <string name="v4_6_group_welcome_message">رسالة ترحيب المجموعة</string> @@ -452,7 +448,7 @@ <string name="settings_section_title_experimenta">تجريبي</string> <string name="icon_descr_group_inactive">المجموعة غير نشطة</string> <string name="files_and_media_section">الملفات والوسائط</string> - <string name="group_members_can_delete">يمكن لأعضاء المجموعة حذف الرسائل المرسلة بشكل لا رجعة فيه.</string> + <string name="group_members_can_delete">يمكن لأعضاء المجموعة حذف الرسائل المرسلة بشكل لا رجعة فيه. (24 ساعة)</string> <string name="fix_connection_not_supported_by_contact">الإصلاح غير مدعوم من قبل جهة الاتصال</string> <string name="group_profile_is_stored_on_members_devices">يُخزّن ملف تعريف المجموعة على أجهزة الأعضاء، وليس على الخوادم.</string> <string name="v4_2_group_links">روابط المجموعة</string> @@ -463,7 +459,7 @@ <string name="file_will_be_received_when_contact_is_online">سيتم استلام الملف عندما تكون جهة اتصالك متصلة بالإنترنت، يرجى الانتظار أو التحقق لاحقًا!</string> <string name="group_full_name_field">الاسم الكامل للمجموعة:</string> <string name="simplex_link_mode_full">رابط كامل</string> - <string name="choose_file">الملف</string> + <string name="choose_file">ملف</string> <string name="delete_group_for_self_cannot_undo_warning">سيتم حذف المجموعة لك - لا يمكن التراجع عن هذا!</string> <string name="failed_to_parse_chat_title">فشل تحميل الدردشة</string> <string name="group_members_can_add_message_reactions">يمكن لأعضاء المجموعة إضافة ردود فعل الرسالة.</string> @@ -511,9 +507,9 @@ <string name="conn_level_desc_indirect">غير مباشر (%1$s)</string> <string name="how_it_works">آلية العمل</string> <string name="incoming_video_call">مكالمة فيديو واردة</string> - <string name="if_you_received_simplex_invitation_link_you_can_open_in_browser">إذا تلقيت رابط دعوة SimpleX Chat، فيمكنك فتحه في متصفحك:</string> + <string name="if_you_received_simplex_invitation_link_you_can_open_in_browser">إذا استلمت رابط دعوة SimpleX Chat، فيمكنك فتحه في متصفحك:</string> <string name="incognito_info_protects">يحمي وضع التخفي خصوصيتك بأستخدام ملف تعريف عشوائي جديد لكل جهة اتصال جديدة.</string> - <string name="info_menu">المعلومات</string> + <string name="info_menu">معلومات</string> <string name="v4_3_improved_privacy_and_security_desc">إخفاء شاشة التطبيق في التطبيقات الحديثة.</string> <string name="v4_3_improved_privacy_and_security">تحسن الخصوصية والأمان</string> <string name="if_you_cannot_meet_in_person_scan_QR_in_video_call_or_ask_for_invitation_link"><![CDATA[إذا لم تتمكن من الالتقاء شخصيًا، فيمكنك <b>مسح رمز QR في مكالمة الفيديو</b>، أو يمكن لجهة الاتصال مشاركة رابط الدعوة.]]></string> @@ -536,7 +532,7 @@ <string name="onboarding_notifications_mode_service">فوري</string> <string name="host_verb">المضيف</string> <string name="hide_notification">إخفاء</string> - <string name="turn_off_battery_optimization"><![CDATA[من أجل استخدامها، <b>يرجى السماح لSimpleX للتشغيل في الخلفية</b> في مربع الحوار التالي. وإلا، سيتم تعطيل الإخطارات.]]></string> + <string name="turn_off_battery_optimization"><![CDATA[من أجل استخدامها، <b>يُرجى السماح لSimpleX للتشغيل في الخلفية</b> في مربع الحوار التالي. وإلا، سيتم تعطيل الإشعارات.]]></string> <string name="in_reply_to">ردًا على</string> <string name="icon_descr_instant_notifications">إشعارات فورية</string> <string name="enter_one_ICE_server_per_line">خوادم ICE (واحد لكل سطر)</string> @@ -553,10 +549,10 @@ <string name="icon_descr_add_members">دعوة الأعضاء</string> <string name="alert_text_skipped_messages_it_can_happen_when">يمكن أن يحدث عندما: \n1. انتهت صلاحية الرسائل في العميل المرسل بعد يومين أو على الخادم بعد 30 يومًا. -\n2. فشل فك تشفير الرسالة، لأنك أو جهة اتصالك استخدمت نسخة احتياطية قديمة من قاعدة البيانات. +\n2. فشل فك تعمية الرسالة، لأنك أو جهة اتصالك استخدمت نسخة احتياطية قديمة من قاعدة البيانات. \n3. اُخترق الاتصال.</string> <string name="v5_1_japanese_portuguese_interface">واجهة أستخدام يابانية وبرتغالية</string> - <string name="alert_text_fragment_encryption_out_of_sync_old_database">يمكن أن يحدث ذلك عندما تستخدم أنت أو اتصالك النسخة الاحتياطية القديمة لقاعدة البيانات.</string> + <string name="alert_text_fragment_encryption_out_of_sync_old_database">يمكن أن يحدث ذلك عندما تستخدم أنت أو اتصالك النُسخة الاحتياطية القديمة لقاعدة البيانات.</string> <string name="group_preview_join_as">انضمام ك%s</string> <string name="invalid_QR_code">رمز QR غير صالح</string> <string name="v4_5_italian_interface">الواجهة الإيطالية</string> @@ -564,11 +560,11 @@ <string name="invite_friends">دعوة الأصدقاء</string> <string name="keychain_error">خطأ في Keychain</string> <string name="invite_to_group_button">دعوة للمجموعة</string> - <string name="message_deletion_prohibited_in_chat">يٌمنع حذف الرسائل بشكل نهائي في هذه المجموعة.</string> + <string name="message_deletion_prohibited_in_chat">يٌمنع حذف الرسائل بشكل لا رجعة فيه في هذه المجموعة.</string> <string name="invalid_message_format">تنسيق الرسالة غير صالح</string> <string name="invalid_data">البيانات غير صالحة</string> <string name="users_delete_data_only">بيانات الملف الشخصي المحلية فقط</string> - <string name="message_deletion_prohibited">يٌمنع حذف الرسائل بشكل نهائي في هذه الدردشة.</string> + <string name="message_deletion_prohibited">يٌمنع حذف الرسائل بشكل لا رجعة فيه في هذه الدردشة.</string> <string name="button_add_members">دعوة الأعضاء</string> <string name="button_leave_group">مغادرة المجموعة</string> <string name="info_row_local_name">الاسم المحلي:</string> @@ -613,13 +609,13 @@ <string name="smp_server_test_download_file">نزّل الملف</string> <string name="auth_disable_simplex_lock">تعطيل قفل SimpleX</string> <string name="edit_verb">تحرير</string> - <string name="display_name__field">اسم العرض:</string> + <string name="display_name__field">اسم الملف الشخصي:</string> <string name="icon_descr_email">البريد الإلكتروني</string> - <string name="display_name">اسم العرض</string> + <string name="display_name">أدخل أسمك:</string> <string name="integrity_msg_duplicate">كرر الرسالة</string> <string name="share_text_disappears_at">يختفي في: %s</string> <string name="disappearing_prohibited_in_this_chat">الرسائل المختفية ممنوعة في هذه الدردشة.</string> - <string name="status_e2e_encrypted">مشفر بين الطريفين</string> + <string name="status_e2e_encrypted">مُعمّى بين الطريفين</string> <string name="icon_descr_edited">حُرر</string> <string name="downgrade_and_open_chat">الرجوع إلى إصدار سابق وفتح الدردشة</string> <string name="direct_messages">رسائل مباشرة</string> @@ -629,7 +625,7 @@ <string name="settings_section_title_device">الجهاز</string> <string name="ttl_week">%d أسبوع</string> <string name="display_name_cannot_contain_whitespace">لا يمكن أن يحتوي اسم العرض على مسافة فارغة.</string> - <string name="encrypted_video_call">مكالمة فيديو مشفرة بين الطريفين</string> + <string name="encrypted_video_call">مكالمة فيديو مُعمّاة بين الطريفين</string> <string name="direct_messages_are_prohibited_in_chat">الرسائل المباشرة بين الأعضاء ممنوعة في هذه المجموعة.</string> <string name="ttl_hour">%d ساعة</string> <string name="ttl_h">%d ساعة</string> @@ -654,7 +650,7 @@ <string name="dont_enable_receipts">لا تُفعل</string> <string name="la_minutes">%d دقائق</string> <string name="la_seconds">%d ثواني</string> - <string name="encrypted_audio_call">مكالمة صوتية مشفرة بين الطريفين</string> + <string name="encrypted_audio_call">مكالمة صوتية مُعمّاة بين الطريفين</string> <string name="ttl_sec">%d ثانية</string> <string name="icon_descr_server_status_disconnected">قُطع الاتصال</string> <string name="disappearing_message">رسالة تختفي</string> @@ -664,7 +660,7 @@ <string name="failed_to_active_user_title">خطأ في تبديل الملف الشخصي!</string> <string name="v5_2_fix_encryption">حافظ على اتصالاتك</string> <string name="ensure_xftp_server_address_are_correct_format_and_unique">تأكد من أن عناوين خادم XFTP بالتنسيق الصحيح، وأن تكون مفصولة بأسطر وليست مكررة.</string> - <string name="marked_deleted_description">وضع علامة \"محذوف\"</string> + <string name="marked_deleted_description">عُلّم محذوف</string> <string name="color_surface">القوائم والتنبيهات</string> <string name="error_saving_xftp_servers">خطأ في حفظ خوادم XFTP</string> <string name="error_loading_smp_servers">خطأ في تحميل خوادم SMP</string> @@ -686,7 +682,7 @@ <string name="enable_automatic_deletion_question">تفعيل الحذف التلقائي للرسائل؟</string> <string name="error_removing_member">خطأ في إزالة العضو</string> <string name="error_setting_address">خطأ في تحديد العنوان</string> - <string name="mark_read">وضع علامة القراءة</string> + <string name="mark_read">علّم مقروءة</string> <string name="receipts_contacts_enable_for_all">تفعيل للجميع</string> <string name="receipts_contacts_enable_keep_overrides">تفعيل (الاحتفاظ بالتجاوزات)</string> <string name="receipts_contacts_title_enable">تفعيل الإيصالات؟</string> @@ -698,7 +694,7 @@ <string name="v5_2_favourites_filter">البحث عن الدردشات بشكل أسرع</string> <string name="enable_receipts_all">تفعيل</string> <string name="v5_2_disappear_one_message_descr">حتى عندما يتم تعطيله في المحادثة.</string> - <string name="v5_2_fix_encryption_descr">إصلاح التشفير بعد استعادة النسخ الاحتياطية.</string> + <string name="v5_2_fix_encryption_descr">إصلاح التعمية بعد استعادة النُسخ الاحتياطية.</string> <string name="v5_2_disappear_one_message">اجعل رسالة واحدة تختفي</string> <string name="error_enabling_delivery_receipts">خطأ في تفعيل إيصالات التسليم!</string> <string name="error_saving_smp_servers">خطأ في حفظ خوادم SMP</string> @@ -707,9 +703,9 @@ <string name="error_synchronizing_connection">خطأ في مزامنة الاتصال</string> <string name="auth_log_in_using_credential">تسجيل الدخول باستخدام بيانات الاعتماد الخاصة بك</string> <string name="error_saving_file">خطأ في حفظ الملف</string> - <string name="mark_unread">وضع علامة غير مقروء</string> + <string name="mark_unread">علّم غير مقروءة</string> <string name="ensure_ICE_server_address_are_correct_format_and_unique">تأكد من أن عناوين خادم WebRTC ICE بالتنسيق الصحيح، وأن تكون مفصولة بأسطر وليست مكررة.</string> - <string name="mark_code_verified">وضع علامة تَحقق منه</string> + <string name="mark_code_verified">علّم تحقق منه</string> <string name="error_saving_user_password">خطأ في حفظ كلمة مرور المستخدم</string> <string name="many_people_asked_how_can_it_deliver"><![CDATA[سأل الكثير من الناس: <i>إذا SimpleX ليس لديه معرّفات مستخدم، كيف يمكنه توصيل الرسائل؟</i>]]></string> <string name="error_saving_group_profile">خطأ في حفظ ملف تعريف المجموعة</string> @@ -720,7 +716,7 @@ <string name="message_delivery_error_title">خطأ في تسليم الرسالة</string> <string name="network_and_servers">الشبكة والخوادم</string> <string name="moderate_verb">إشراف</string> - <string name="mobile_tap_open_in_mobile_app_then_tap_connect_in_app"><![CDATA[📱 للجوال: انقر فوق <b>فتح في تطبيق الجوال</b> ، ثم انقر فوق <b>اتصال</b> في التطبيق.]]></string> + <string name="mobile_tap_open_in_mobile_app_then_tap_connect_in_app"><![CDATA[📱 للجوال: انقر فوق <b>فتح في تطبيق الجوال</b>، ثم انقر فوق <b>اتصال</b> في التطبيق.]]></string> <string name="share_text_moderated_at">تحت الإشراف في: %s</string> <string name="message_reactions_prohibited_in_this_chat">ردود الفعل الرسائل ممنوعة في هذه الدردشة.</string> <string name="moderated_item_description">مُشرف بواسطة %s</string> @@ -752,7 +748,7 @@ <string name="v4_5_message_draft">مسودة الرسالة</string> <string name="v4_5_multiple_chat_profiles">ملفات تعريف دردشة متعددة</string> <string name="settings_notification_preview_title">معاينة الإشعار</string> - <string name="status_no_e2e_encryption">لا يوجد تشفير بين الطريفين</string> + <string name="status_no_e2e_encryption">لا يوجد تعمية بين الطريفين</string> <string name="chat_preferences_no">لا</string> <string name="notification_preview_new_message">رسالة جديدة</string> <string name="images_limit_desc">يمكن إرسال 10 صور فقط في نفس الوقت</string> @@ -760,7 +756,7 @@ <string name="feature_offered_item_with_param">متوفرة %s: %2s</string> <string name="notifications_will_be_hidden">سيتم تسليم الإشعارات فقط حتى يتوقف التطبيق!</string> <string name="no_filtered_chats">لا توجد محادثات مُصفاة</string> - <string name="no_received_app_files">لا توجد ملفات مستلمة أو مرسلة</string> + <string name="no_received_app_files">لا توجد ملفات مُستلمة أو مُرسلة</string> <string name="shutdown_alert_desc">ستتوقف الإشعارات عن العمل حتى تعيد تشغيل التطبيق</string> <string name="new_passcode">رمز مرور جديد</string> <string name="new_database_archive">أرشيف قاعدة بيانات جديدة</string> @@ -768,7 +764,7 @@ <string name="network_use_onion_hosts_prefer_desc">سيتم استخدام مضيفات البصل عند توفرها.</string> <string name="network_use_onion_hosts_no_desc">لن يتم استخدام مضيفات البصل.</string> <string name="no_contacts_selected">لم تٌحدد جهات اتصال</string> - <string name="v4_6_group_moderation_descr">يمكن للمسؤولين الآن: + <string name="v4_6_group_moderation_descr">يمكّن للمشرف الآن: \n- حذف رسائل الأعضاء. \n- تعطيل الأعضاء (دور \"المراقب\")</string> <string name="settings_notifications_mode_title">خدمة الإشعار</string> @@ -799,7 +795,7 @@ <string name="new_passphrase">عبارة مرور جديدة…</string> <string name="icon_descr_server_status_pending">يرجى الانتظار</string> <string name="enter_passphrase_notification_title">كلمة المرور مطلوبة</string> - <string name="paste_the_link_you_received">ألصق الرابط المُستلَم</string> + <string name="paste_the_link_you_received">ألصِق الرابط الذي استلمته</string> <string name="only_owners_can_enable_files_and_media">فقط مالكي المجموعة يمكنهم تفعيل الملفات والوسائط.</string> <string name="only_group_owners_can_enable_voice">فقط مالكي المجموعة يمكنهم تفعيل الرسائل الصوتية.</string> <string name="only_stored_on_members_devices">(يخزن فقط بواسطة أعضاء المجموعة)</string> @@ -809,7 +805,7 @@ <string name="only_your_contact_can_send_disappearing">فقط جهة اتصالك يمكنها إرسال رسائل تختفي.</string> <string name="only_your_contact_can_add_message_reactions">جهة اتصالك فقط يمكنها إضافة تفاعلات على الرسالة</string> <string name="only_group_owners_can_change_prefs">فقط مالكي المجموعة يمكنهم تغيير تفضيلات المجموعة.</string> - <string name="only_your_contact_can_delete">جهة اتصالك فقط يمكنها حذف الرسائل نهائيا (يمكنك تعليم الرسالة للحذف).</string> + <string name="only_your_contact_can_delete">جهة اتصالك فقط يمكنها حذف الرسائل بشكل لا رجعة فيه (يمكنك تعليم الرسالة للحذف). (24 ساعة)</string> <string name="only_you_can_send_voice">أنت فقط يمكنك إرسال رسائل صوتية.</string> <string name="open_verb">افتح</string> <string name="passcode_not_changed">لم يتم تغيير كلمة المرور!</string> @@ -821,7 +817,7 @@ <string name="open_chat">افتح الدردشة</string> <string name="simplex_link_mode_browser_warning">فتح الرابط في المتصفح قد يقلل خصوصية وحماية اتصالك. الروابط غير الموثوقة من SimpleX ستكون باللون الأحمر</string> <string name="only_you_can_add_message_reactions">أنت فقط يمكنك إضافة تفاعل على الرسالة.</string> - <string name="only_you_can_delete_messages">أنت فقط يمكنك حذف الرسائل نهائيا (يمكن للمستلم تعليمها للحذف)</string> + <string name="only_you_can_delete_messages">أنت فقط يمكنك حذف الرسائل بشكل لا رجعة فيه (يمكن للمستلم تعليمها للحذف). (24 ساعة)</string> <string name="only_you_can_send_disappearing">أنت فقط يمكنك إرسال رسائل تختفي</string> <string name="only_you_can_make_calls">أنت فقط يمكنك إجراء المكالمات.</string> <string name="only_your_contact_can_make_calls">فقط جهة اتصالك يمكنها إجراء المكالمات.</string> @@ -833,7 +829,7 @@ <string name="call_connection_peer_to_peer">ندّ لِندّ</string> <string name="people_can_connect_only_via_links_you_share">يمكن للناس التواصل معك فقط عبر الرابط الذي تقوم بمشاركته</string> <string name="icon_descr_call_pending_sent">مكالمة في الانتظار</string> - <string name="only_client_devices_store_contacts_groups_e2e_encrypted_messages"><![CDATA[تقوم أجهزة العميل فقط بتخزين ملفات تعريف المستخدمين وجهات الاتصال والمجموعات والرسائل المرسلة باستخدام <b>تشفير ثنائي الطبقات من بين الطريفين</b>.]]></string> + <string name="only_client_devices_store_contacts_groups_e2e_encrypted_messages"><![CDATA[تقوم أجهزة العميل فقط بتخزين ملفات تعريف المستخدمين وجهات الاتصال والمجموعات والرسائل المُرسلة باستخدام <b>تعمية ثنائية الطبقات من بين الطريفين</b>.]]></string> <string name="reset_color">إعادة تعيين الألوان</string> <string name="save_verb">حفظ</string> <string name="smp_servers_preset_address">عنوان الخادم المحدد مسبقًا</string> @@ -841,12 +837,12 @@ <string name="onboarding_notifications_mode_periodic">دوري</string> <string name="restart_the_app_to_use_imported_chat_database">أعد تشغيل التطبيق لاستخدام قاعدة بيانات الدردشة المستوردة.</string> <string name="receiving_via">الاستلام عبر</string> - <string name="please_check_correct_link_and_maybe_ask_for_a_new_one">يرجى التحقق من استخدامك للرابط الصحيح أو اطلب من جهة اتصالك أن ترسل لك رابطًا آخر.</string> + <string name="please_check_correct_link_and_maybe_ask_for_a_new_one">يُرجى التحقق من استخدامك للرابط الصحيح أو اطلب من جهة اتصالك أن ترسل لك رابطًا آخر.</string> <string name="periodic_notifications_disabled">الإشعارات الدورية مُعطَّلة</string> <string name="image_descr_profile_image">صورة الملف الشخصي</string> <string name="onboarding_notifications_mode_title">الإشعارات خاصة</string> <string name="store_passphrase_securely_without_recover">يرجى تخزين عبارة المرور بشكل آمن، فلن تتمكن من الوصول إلى الدردشة إذا فقدتها.</string> - <string name="contact_developers">يرجى تحديث التطبيق والاتصال بالمطورين.</string> + <string name="contact_developers">يُرجى تحديث التطبيق والتواصل مع المطورين.</string> <string name="read_more_in_user_guide_with_link"><![CDATA[اقرأ المزيد في <font color="#0088ff">دليل المستخدم</font>.]]></string> <string name="auth_open_chat_profiles">افتح ملفات تعريف الدردشة</string> <string name="revoke_file__confirm">اسحب الوصول</string> @@ -934,9 +930,9 @@ <string name="group_welcome_preview">معاينة</string> <string name="error_smp_test_certificate">من المحتمل أن الملف المرجعي للشهادة في عنوان الخادم غير صحيح</string> <string name="simplex_service_notification_text">يتم استلام الرسائل…</string> - <string name="observer_cant_send_message_desc">يرجى الاتصال بمسؤول المجموعة.</string> + <string name="observer_cant_send_message_desc">يُرجى الاتصال بمشرف المجموعة.</string> <string name="sync_connection_force_confirm">أعد التفاوض</string> - <string name="sync_connection_force_question">إعادة تفاوض التشفير</string> + <string name="sync_connection_force_question">إعادة تفاوض التعمية</string> <string name="revoke_file__action">سحب وصول الملف</string> <string name="revoke_file__title">سحب وصول الملف؟</string> <string name="toast_permission_denied">رٌفض الإذن!</string> @@ -951,7 +947,7 @@ <string name="save_and_notify_contact">حفظ وإشعار جهة الاتصال</string> <string name="settings_restart_app">إعادة التشغيل</string> <string name="share_text_received_at">استلمت في: %s</string> - <string name="renegotiate_encryption">إعادة تفاوض التشفير</string> + <string name="renegotiate_encryption">إعادة تفاوض التعمية</string> <string name="sender_at_ts">%s في %s</string> <string name="save_group_profile">حفظ ملف المجموعة</string> <string name="color_secondary">ثانوي</string> @@ -975,7 +971,7 @@ <string name="sending_via">إرسال عبر</string> <string name="conn_stats_section_title_servers">الخوادم</string> <string name="v4_2_security_assessment">تقييم الأمان</string> - <string name="v4_4_disappearing_messages_desc">الرسائل المرسلة سيتم حذفها بعد المدة المحددة.</string> + <string name="v4_4_disappearing_messages_desc">الرسائل المرسلة سيتم حذفها بعد المدة المحدّدة.</string> <string name="v4_6_group_welcome_message_descr">تعيين رسالة تظهر للأعضاء الجدد!</string> <string name="set_passcode">تعيين كلمة المرور</string> <string name="share_text_sent_at">تم إرساله في: %s</string> @@ -1041,9 +1037,9 @@ <string name="image_descr_simplex_logo">شعار SimpleX</string> <string name="icon_descr_simplex_team">فريق SimpleX</string> <string name="show_QR_code">عرض رمز QR</string> - <string name="is_verified">%s تم التحقق منه</string> + <string name="is_verified">تم التحقق %s</string> <string name="smp_servers_test_some_failed">فشلت بعض الخوادم في الاختبار:</string> - <string name="send_link_previews">إرسال معاينات الارتباط</string> + <string name="send_link_previews">إرسال معاينات الرابط</string> <string name="skip_inviting_button">تخطي دعوة الأعضاء</string> <string name="stop_chat_question">إيقاف الدردشة؟</string> <string name="show_call_on_lock_screen">عرض</string> @@ -1066,7 +1062,7 @@ <string name="star_on_github">اضع نجمة على GitHub</string> <string name="stop_sharing_address">إيقاف مشاركة العنوان؟</string> <string name="stop_sharing">إيقاف المشاركة</string> - <string name="stop_chat_to_export_import_or_delete_chat_database">أوقف الدردشة لتصدير أو استيراد أو حذف قاعدة بيانات الدردشة. لن تتمكن من تلقي الرسائل وإرسالها أثناء إيقاف الدردشة.</string> + <string name="stop_chat_to_export_import_or_delete_chat_database">أوقف الدردشة لتصدير أو استيراد أو حذف قاعدة بيانات الدردشة. لن تتمكّن من استلام الرسائل وإرسالها أثناء إيقاف الدردشة.</string> <string name="stop_chat_to_enable_database_actions">أوقف الدردشة لتمكين إجراءات قاعدة البيانات.</string> <string name="chat_item_ttl_seconds">%s ثانية/ثواني</string> <string name="callstate_starting">يبدأ…</string> @@ -1094,8 +1090,8 @@ <string name="language_system">النظام</string> <string name="theme">السمة</string> <string name="to_start_a_new_chat_help_header">لبدء محادثة جديدة</string> - <string name="to_verify_compare">للتحقق من التشفير بين الطريفين مع جهة اتصالك، قارن (أو امسح) الرمز الموجود على أجهزتك.</string> - <string name="group_is_decentralized">المجموعة لامركزية بالكامل - فهي مرئية فقط للأعضاء.</string> + <string name="to_verify_compare">للتحقق من التعمية بين الطريفين مع جهة اتصالك، قارن (أو امسح) الرمز الموجود على أجهزتك.</string> + <string name="group_is_decentralized">لامركزية بالكامل – مرئية للأعضاء فقط.</string> <string name="theme_system">النظام</string> <string name="error_smp_test_failed_at_step">فشل الاختبار في الخطوة %s.</string> <string name="v4_5_italian_interface_descr">بفضل المستخدمين - المساهمة عبر Weblate!</string> @@ -1130,7 +1126,6 @@ <string name="database_initialization_error_desc">قاعدة البيانات لا تعمل بشكل صحيح. انقر لمعرفة المزيد</string> <string name="theme_colors_section_title">ألوان السمة</string> <string name="tap_to_activate_profile">انقر لتنشيط الملف الشخصي.</string> - <string name="should_be_at_least_one_profile">يجب أن يكون هناك ملف تعريف مستخدم واحد على الأقل.</string> <string name="v4_5_transport_isolation">عزل النقل</string> <string name="this_string_is_not_a_connection_link">هذه السلسلة ليست رابط اتصال!</string> <string name="receipts_section_description">هذه الإعدادات لملف التعريف الحالي الخاص بك</string> @@ -1140,10 +1135,9 @@ <string name="v5_2_message_delivery_receipts_descr">فقدنا القراد الثاني! ✅</string> <string name="whats_new_thanks_to_users_contribute_weblate">بفضل المستخدمين - المساهمة عبر Weblate!</string> <string name="database_backup_can_be_restored">لم تكتمل محاولة تغيير عبارة مرور قاعدة البيانات.</string> - <string name="enter_passphrase_notification_desc">لتلقي الإخطارات، يرجى إدخال عبارة مرور قاعدة البيانات</string> - <string name="should_be_at_least_one_visible_profile">يجب أن يكون هناك ملف تعريف مستخدم مرئي واحد على الأقل.</string> + <string name="enter_passphrase_notification_desc">لاستلام الإشعارات، يُرجى إدخال عبارة مرور قاعدة البيانات</string> <string name="la_lock_mode_system">مصادقة النظام</string> - <string name="sync_connection_force_desc">يعمل التشفير واتفاقية التشفير الجديدة غير مطلوبة. قد ينتج عن ذلك أخطاء في الاتصال!</string> + <string name="sync_connection_force_desc">يعمل التعمية واتفاقية التعمية الجديدة غير مطلوبة. قد ينتج عن ذلك أخطاء في الاتصال!</string> <string name="image_decoding_exception_desc">لا يمكن فك ترميز الصورة. من فضلك، جرب صورة مختلفة أو تواصل مع المطورين.</string> <string name="moderate_message_will_be_deleted_warning">سيتم حذف الرسالة لجميع الأعضاء.</string> <string name="images_limit_title">الصور كثيرة!</string> @@ -1155,20 +1149,20 @@ <string name="alert_text_msg_bad_id">معرف الرسالة التالية غير صحيح (أقل أو يساوي السابق). \nيمكن أن يحدث ذلك بسبب بعض العلل أو عندما يُخترق الاتصال.</string> <string name="unfavorite_chat">إزالة من المفضلة</string> - <string name="trying_to_connect_to_server_to_receive_messages">محاولة الاتصال بالخادم المستخدم لتلقي الرسائل من جهة الاتصال هذه.</string> + <string name="trying_to_connect_to_server_to_receive_messages">محاولة الاتصال بالخادم المستخدم لاستلام الرسائل من جهة الاتصال هذه.</string> <string name="choose_file_title">اختيار ملف</string> <string name="icon_descr_sent_msg_status_unauthorized_send">إرسال غير مصرح به</string> - <string name="trying_to_connect_to_server_to_receive_messages_with_error">محاولة الاتصال بالخادم المستخدم لتلقي الرسائل من جهة الاتصال هذه (خطأ: %1$s).</string> + <string name="trying_to_connect_to_server_to_receive_messages_with_error">محاولة الاتصال بالخادم المستخدم لاستلام الرسائل من جهة الاتصال هذه (خطأ: %1$s).</string> <string name="la_notice_turn_on">تشغيل</string> <string name="webrtc_ice_servers">خوادم WebRTC ICE</string> <string name="alert_title_cant_invite_contacts_descr">أنت تستخدم ملفًا شخصيًا متخفيًا لهذه المجموعة - لمنع مشاركة ملفك الشخصي الرئيسي الذي يدعو جهات الاتصال غير مسموح به</string> <string name="snd_group_event_changed_member_role">غيّرتَ دور %s إلى %s</string> <string name="chat_preferences_yes">نعم</string> - <string name="connected_to_server_to_receive_messages_from_contact">أنت متصل بالخادم المستخدم لتلقي الرسائل من جهة الاتصال هذه.</string> + <string name="connected_to_server_to_receive_messages_from_contact">أنت متصل بالخادم المستخدم لاستلام الرسائل من جهة الاتصال هذه.</string> <string name="sender_you_pronoun">أنت</string> <string name="description_you_shared_one_time_link">لقد شاركت رابط لمرة واحدة</string> - <string name="profile_will_be_sent_to_contact_sending_link">سيتم إرسال ملف التعريفك إلى جهة الاتصال التي تلقيت منها هذا الارتباط.</string> - <string name="you_will_join_group">ستنضم إلى مجموعة يشير إليها هذا الرابط وتتصل بأعضائها.</string> + <string name="profile_will_be_sent_to_contact_sending_link">سيتم إرسال ملف التعريفك إلى جهة الاتصال التي استلمت منها هذا الرابط.</string> + <string name="you_will_join_group">سوف تتصل بجميع أعضاء المجموعة.</string> <string name="your_chat_profiles">ملفات تعريف الدردشة الخاصة بك</string> <string name="your_simplex_contact_address">عنوان SimpleX الخاص بك</string> <string name="your_SMP_servers">خوادم SMP الخاصة بك</string> @@ -1226,17 +1220,17 @@ <string name="v4_3_irreversible_message_deletion_desc">يمكن أن تسمح جهات اتصالك بحذف الرسائل بالكامل.</string> <string name="unknown_message_format">تنسيق رسالة غير معروف</string> <string name="description_via_one_time_link">عبر رابط لمرة واحدة</string> - <string name="video_call_no_encryption">مكالمة الفيديو ليست مشفرة بين الطريفين</string> + <string name="video_call_no_encryption">مكالمة الفيديو ليست مُعمّاة بين الطريفين</string> <string name="snd_conn_event_switch_queue_phase_completed">غيّرتَ العنوان</string> <string name="you_will_be_connected_when_your_contacts_device_is_online">سوف تكون متصلاً عندما يكون جهاز جهة الاتصال الخاصة بك متصلاً بالإنترنت، يرجى الانتظار أو التحقق لاحقًا!</string> <string name="snd_group_event_user_left">غادرت</string> <string name="you_must_use_the_most_recent_version_of_database">يجب عليك استخدام أحدث إصدار من قاعدة بيانات الدردشة الخاصة بك على جهاز واحد فقط، وإلا فقد تتوقف عن تلقي الرسائل من بعض جهات الاتصال.</string> <string name="video_will_be_received_when_contact_is_online">سيتم استلام الفيديو عندما تكون جهة اتصالك متصلة بالإنترنت، يرجى الانتظار أو التحقق لاحقًا!</string> - <string name="you_control_servers_to_receive_your_contacts_to_send"><![CDATA[يمكنك التحكم من خلال الخادم (الخوادم) <b>لتلقي</b> الرسائل وجهات اتصالك - الخوادم التي تستخدمها لمراسلتهم.]]></string> + <string name="you_control_servers_to_receive_your_contacts_to_send"><![CDATA[يمكنك التحكم من خلال الخادم (الخوادم) <b>لاستلام</b> الرسائل وجهات اتصالك - الخوادم التي تستخدمها لمراسلتهم.]]></string> <string name="you_can_share_this_address_with_your_contacts">يمكنك مشاركة هذا العنوان مع جهات اتصالك للسماح لهم بالاتصال بـ%s.</string> <string name="snd_group_event_member_deleted">أُزيلت %1$s</string> <string name="update_database">تحديث</string> - <string name="database_is_not_encrypted">قاعدة بيانات الدردشة الخاصة بك غير مشفرة - قم بتعيين عبارة المرور لحمايتها.</string> + <string name="database_is_not_encrypted">قاعدة بيانات الدردشة الخاصة بك غير مُعمّاة - عيّن عبارة مرور لحمايتها.</string> <string name="wrong_passphrase">عبارة مرور قاعدة بيانات خاطئة</string> <string name="group_main_profile_sent">سيتم إرسال ملف تعريف الدردشة الخاص بك إلى أعضاء المجموعة</string> <string name="personal_welcome">مرحبًا! %1$s</string> @@ -1305,26 +1299,26 @@ <string name="upgrade_and_open_chat">قم بالترقية وفتح الدردشة</string> <string name="button_welcome_message">رسالة الترحيب</string> <string name="description_via_contact_address_link">عبر رابط عنوان الاتصال</string> - <string name="connection_error_auth_desc">ما لم يحذف جهة الاتصال الاتصال أو تم استخدام هذا الرابط بالفعل، فقد يكون خطأ - الرجاء الإبلاغ عنه. -\nللاتصال، يرجى مطالبة جهة اتصالك بإنشاء ارتباط اتصال آخر والتحقق من أن لديك اتصال شبكة ثابت.</string> + <string name="connection_error_auth_desc">ما لم يحذف جهة الاتصال الاتصال أو استُخدم هذا الرابط بالفعل، فقد يكون خطأ - الرجاء الإبلاغ عنه. +\nللاتصال، يُرجى مطالبة جهة اتصالك بإنشاء رابط اتصال آخر والتحقق من أن لديك اتصال شبكة ثابت.</string> <string name="your_chat_profile_will_be_sent_to_your_contact">سيتم إرسال ملف تعريف الدردشة الخاص بك \nإلى جهة اتصالك</string> <string name="user_unhide">إلغاء الإخفاء</string> <string name="incognito_random_profile">ملفك الشخصي العشوائي</string> - <string name="you_will_still_receive_calls_and_ntfs">ستستمر في تلقي المكالمات والإشعارات من الملفات الشخصية المكتومة عندما تكون نشطة.</string> + <string name="you_will_still_receive_calls_and_ntfs">ستستمر في استلام المكالمات والإشعارات من الملفات الشخصية المكتومة عندما تكون نشطة.</string> <string name="chat_preferences_you_allow">انت تسمح بها</string> <string name="icon_descr_video_call">مكالمة فيديو</string> <string name="voice_messages_are_prohibited">الرسائل الصوتية ممنوعة في هذه الدردشة.</string> <string name="auth_unlock">فتح القفل</string> <string name="smp_server_test_upload_file">رفع الملف</string> - <string name="la_could_not_be_verified">لا يمكن التحقق منك؛ حاول مرة اخرى.</string> + <string name="la_could_not_be_verified">لا يمكن التحقق منك؛ الرجاء المحاولة مرة اخرى.</string> <string name="voice_message">رسالة صوتية</string> <string name="voice_message_send_text">رسالة صوتية…</string> <string name="group_preview_you_are_invited">أنت مدعو إلى المجموعة</string> <string name="observer_cant_send_message_title">لا يمكنك إرسال رسائل!</string> <string name="you_need_to_allow_to_send_voice">تحتاج إلى السماح لجهة الاتصال الخاصة بك بإرسال رسائل صوتية لتتمكن من إرسالها.</string> <string name="contact_sent_large_file">أرسلت جهة اتصالك ملفًا أكبر من الحجم الأقصى المعتمد حاليًا (%1$s).</string> - <string name="you_can_connect_to_simplex_chat_founder"><![CDATA[يمكنك <font color=#0088ff>الاتصال بمطوري SimpleX Chat لطرح أي أسئلة وتلقي التحديثات</font>.]]></string> + <string name="you_can_connect_to_simplex_chat_founder"><![CDATA[يمكنك <font color="#0088ff">الاتصال بمطوري SimpleX Chat لطرح أي أسئلة وتلقي التحديثات</font>.]]></string> <string name="smp_servers_your_server">خادمك</string> <string name="your_profile_is_stored_on_device_and_shared_only_with_contacts_simplex_cannot_see_it">يُخزن ملف تعريفك على جهازك ومشاركته فقط مع جهات اتصالك. لا تستطيع خوادم SimpleX رؤية ملف تعريفك.</string> <string name="icon_descr_video_off">الفيديو مقفل</string> @@ -1345,7 +1339,7 @@ <string name="receipts_groups_enable_keep_overrides">تفعيل (الاحتفاظ بتجاوزات المجموعة)</string> <string name="receipts_groups_title_enable">تفعيل الإيصالات للمجموعات؟</string> <string name="no_info_on_delivery">لا توجد معلومات عن التسليم</string> - <string name="no_selected_chat">لا توجد دردشة محددة</string> + <string name="no_selected_chat">لا توجد دردشة محدّدة</string> <string name="receipts_groups_override_disabled">إرسال الإيصالات مُعطَّلة لـ%d مجموعات</string> <string name="receipts_section_groups">مجموعات صغيرة (الحد الأقصى 20)</string> <string name="connect_via_member_address_alert_title">تواصل مباشرةً؟</string> @@ -1354,15 +1348,15 @@ <string name="connect_use_current_profile">استخدم ملف التعريف الحالي</string> <string name="disable_notifications_button">تعطيل الإشعارات</string> <string name="turn_off_system_restriction_button">افتح إعدادات التطبيق</string> - <string name="system_restricted_background_desc">لا يمكن تشغيل SimpleX في الخلفية. ستتلقى الإشعارات فقط عندما يكون التطبيق قيد التشغيل.</string> + <string name="system_restricted_background_desc">لا يمكن تشغيل SimpleX في الخلفية. ستستلم الإشعارات فقط عندما يكون التطبيق قيد التشغيل.</string> <string name="connect__a_new_random_profile_will_be_shared">سيتم مشاركة ملف تعريف عشوائي جديد.</string> <string name="paste_the_link_you_received_to_connect_with_your_contact">ألصق الرابط المُستلَم للتواصل مع جهة اتصالك…</string> <string name="connect__your_profile_will_be_shared">ستتم مشاركة ملفك الشخصي %1$s.</string> <string name="system_restricted_background_in_call_desc">قد يغلق التطبيق بعد دقيقة واحدة في الخلفية.</string> <string name="turn_off_battery_optimization_button">سماح</string> <string name="system_restricted_background_in_call_title">لا مكالمات في الخلفية</string> - <string name="system_restricted_background_warn"><![CDATA[لتمكين الإشعارات، يرجى اختيار <b>استهلاك بطارية التطبيق</b> / <b>غير مقيد</b> في إعدادات التطبيق.]]></string> - <string name="system_restricted_background_in_call_warn"><![CDATA[لإجراء مكالمات في الخلفية، يرجى اختيار <b>استهلاك بطارية التطبيق</b> / <b>غير مقيد</b> في إعدادات التطبيق.]]></string> + <string name="system_restricted_background_warn"><![CDATA[لتفعيل الإشعارات، يُرجى اختيار <b>استهلاك بطارية التطبيق</b> / <b>غير مقيد</b> في إعدادات التطبيق.]]></string> + <string name="system_restricted_background_in_call_warn"><![CDATA[لإجراء مكالمات في الخلفية، يُرجى اختيار <b>استهلاك بطارية التطبيق</b> / <b>غير مقيد</b> في إعدادات التطبيق.]]></string> <string name="connect_use_new_incognito_profile">استخدم ملف تعريف متخفي جديد</string> <string name="you_invited_a_contact">أنت دعوت جهة اتصال</string> <string name="privacy_message_draft">مسودة الرسالة</string> @@ -1370,10 +1364,10 @@ <string name="privacy_show_last_messages">إظهار الرسائل الأخيرة</string> <string name="rcv_group_event_n_members_connected">%s، %s و %d أعضاء آخرين متصلون</string> <string name="rcv_group_event_3_members_connected">%s، %s و %s متصل</string> - <string name="database_will_be_encrypted_and_passphrase_stored_in_settings">سيتم تشفير قاعدة البيانات وتخزين عبارة المرور في الإعدادات.</string> + <string name="database_will_be_encrypted_and_passphrase_stored_in_settings">سيتم تعمية قاعدة البيانات وتخزين عبارة المرور في الإعدادات.</string> <string name="you_can_change_it_later">يُخزين عبارة المرور العشوائية في الإعدادات كنص عادي. \nيمكنك تغييره لاحقا.</string> - <string name="database_encryption_will_be_updated_in_settings">سيتم تحديث عبارة مرور تشفير قاعدة البيانات وتخزينها في الإعدادات.</string> + <string name="database_encryption_will_be_updated_in_settings">سيتم تحديث عبارة مرور تعمية قاعدة البيانات وتخزينها في الإعدادات.</string> <string name="remove_passphrase_from_settings">هل تريد إزالة عبارة المرور من الإعدادات؟</string> <string name="use_random_passphrase">استخدم عبارة مرور عشوائية</string> <string name="save_passphrase_in_settings">حفظ عبارة المرور في الإعدادات</string> @@ -1382,12 +1376,12 @@ <string name="open_database_folder">افتح مجلد قاعدة البيانات</string> <string name="passphrase_will_be_saved_in_settings">سيتم تخزين عبارة المرور في الإعدادات كنص عادي بعد تغييرها أو إعادة تشغيل التطبيق.</string> <string name="settings_is_storing_in_clear_text">يُخزين عبارة المرور في الإعدادات كنص عادي.</string> - <string name="socks_proxy_setting_limitations"><![CDATA[<b>يُرجى الملاحظة</b>: يتم توصيل مرحلات الرسائل والملفات عبر وكيل SOCKS. تستخدم المكالمات وإرسال معاينات الارتباط الاتصال المباشر.]]></string> - <string name="encrypt_local_files">تشفير الملفات المحلية</string> - <string name="v5_3_encrypt_local_files">تشفير الملفات والوسائط المخزنة</string> + <string name="socks_proxy_setting_limitations"><![CDATA[<b>يُرجى الملاحظة</b>: يتم توصيل مرحلات الرسائل والملفات عبر وكيل SOCKS. تستخدم المكالمات وإرسال معاينات الروابط الاتصال المباشر.]]></string> + <string name="encrypt_local_files">عَمِّ الملفات المحلية</string> + <string name="v5_3_encrypt_local_files">عَمِّ الملفات والوسائط المخزنة</string> <string name="v5_3_new_desktop_app">تطبيق سطح المكتب الجديد!</string> <string name="v5_3_new_interface_languages">6 لغات واجهة جديدة</string> - <string name="v5_3_encrypt_local_files_descr">يقوم التطبيق بتشفير الملفات المحلية الجديدة (باستثناء مقاطع الفيديو).</string> + <string name="v5_3_encrypt_local_files_descr">يُعمِّي الملفات المحلية الجديدة (باستثناء مقاطع الفيديو).</string> <string name="v5_3_discover_join_groups">اكتشاف والانضمام إلى المجموعات</string> <string name="v5_3_new_interface_languages_descr">العربية والبلغارية والفنلندية والعبرية والتايلاندية والأوكرانية - شكرًا للمستخدمين و Weblate.</string> <string name="v5_3_new_desktop_app_descr">إنشاء ملف تعريف جديد في تطبيق سطح المكتب. 💻</string> @@ -1405,8 +1399,235 @@ <string name="v5_4_better_groups">مجموعات أفضل</string> <string name="rcv_group_and_other_events">و%d أحداث أخرى</string> <string name="connect_plan_already_joining_the_group">جارٍ انضمام بالفعل إلى المجموعة!</string> - <string name="block_member_confirmation">حجب</string> + <string name="block_member_confirmation">حظر</string> <string name="bad_desktop_address">عنوان سطح المكتب غير صالح</string> <string name="block_member_desc">سيتم إخفاء كافة الرسائل الجديدة من %s!</string> - <string name="blocked_item_description">محجوب</string> + <string name="blocked_item_description">محظور</string> + <string name="v5_4_block_group_members">حظر أعضاء المجموعة</string> + <string name="rcv_direct_event_contact_deleted">جهة الاتصال المحذوفة</string> + <string name="v5_4_incognito_groups_descr">أنشِئ مجموعة باستخدام ملف تعريف عشوائي.</string> + <string name="create_group_button">أنشِئ مجموعة</string> + <string name="create_another_profile_button">أنشِئ ملف تعريف</string> + <string name="connected_desktop">سطح المكتب متصل</string> + <string name="multicast_connect_automatically">اتصل تلقائيًا</string> + <string name="desktop_address">عنوان سطح المكتب</string> + <string name="marked_deleted_items_description">وضّع علامة \"محذوفة\" على %d من الرسائل</string> + <string name="discover_on_network">اكتشف عبر الشبكة المحلية</string> + <string name="connect_plan_connect_via_link">اتصل عبر الرابط؟</string> + <string name="connect_plan_connect_to_yourself">اتصل بنفسك؟</string> + <string name="desktop_device">سطح المكتب</string> + <string name="connected_to_desktop">متصل بسطح المكتب</string> + <string name="connecting_to_desktop">جار الاتصال بسطح المكتب</string> + <string name="desktop_devices">أجهزة سطح المكتب</string> + <string name="correct_name_to">الاسم الصحيح لـ%s؟</string> + <string name="delete_messages__question">حذف %d رسالة؟</string> + <string name="connect_with_contact_name_question">اتصل مع %1$s؟</string> + <string name="blocked_items_description">%d رسالة محظورة</string> + <string name="block_member_button">حظر العضو</string> + <string name="connected_mobile">الجوّال متصل</string> + <string name="delete_and_notify_contact">حذف وإشعار جهة الاتصال</string> + <string name="desktop_connection_terminated">انتهى الاتصال</string> + <string name="connect_to_desktop">اتصل بسطح المكتب</string> + <string name="disconnect_remote_host">قطع الاتصال</string> + <string name="block_member_question">حظر العضو؟</string> + <string name="rcv_group_events_count">%d أحداث مجموعة</string> + <string name="group_member_role_author">الكاتب</string> + <string name="connected_to_mobile">متصل بالجوّال</string> + <string name="devices">الأجهزة</string> + <string name="multicast_discoverable_via_local_network">مُكتشف عبر الشبكة المحلية</string> + <string name="disconnect_desktop_question">قطع اتصال سطح المكتب؟</string> + <string name="desktop_app_version_is_incompatible">إصدار تطبيق سطح المكتب %s غير متوافق مع هذا التطبيق.</string> + <string name="expand_verb">توسيع</string> + <string name="connect_plan_repeat_connection_request">هل تريد تكرار طلب الاتصال؟</string> + <string name="encryption_renegotiation_error">خطأ في إعادة التفاوض بشأن التعمية</string> + <string name="connect_plan_you_are_already_connecting_to_vName"><![CDATA[أنت متصل بالفعل بـ <b>%1$s</b>.]]></string> + <string name="error_alert_title">خطأ</string> + <string name="connect_plan_you_are_already_joining_the_group_via_this_link">لقد انضممت بالفعل إلى المجموعة عبر هذا الرابط.</string> + <string name="group_members_2">%s و%s</string> + <string name="new_mobile_device">جوّال جديد</string> + <string name="only_one_device_can_work_at_the_same_time">يمكن لجهاز واحد فقط العمل في نفس الوقت</string> + <string name="connect_plan_join_your_group">انضمام إلى مجموعتك؟</string> + <string name="connect_plan_you_are_already_joining_the_group_vName"><![CDATA[أنت تنضم بالفعل إلى المجموعة <b>%1$s</b>.]]></string> + <string name="v5_4_link_mobile_desktop">ربط تطبيقات الجوّال وسطح المكتب! 🔗</string> + <string name="connect_plan_this_is_your_own_one_time_link">هذا هو الرابط الخاص بك لمرة واحدة!</string> + <string name="connect_plan_group_already_exists">المجموعة موجودة بالفعل!</string> + <string name="v5_4_link_mobile_desktop_descr">عبر بروتوكول آمن مقاوم للكم.</string> + <string name="open_on_mobile_and_scan_qr_code"><![CDATA[افتح <i>الاستخدام من سطح المكتب</i> في تطبيق الجوّال وامسح رمز QR ضوئيًا.]]></string> + <string name="v5_4_block_group_members_descr">لإخفاء الرسائل غير المرغوب فيها.</string> + <string name="desktop_incompatible_version">نُسخة غير متوافقة</string> + <string name="new_desktop"><![CDATA[<i>(جديد)</i>]]></string> + <string name="unlink_desktop_question">فك ربط سطح المكتب؟</string> + <string name="linked_desktop_options">خيارات سطح المكتب المرتبطة</string> + <string name="video_decoding_exception_desc">لا يمكن فك تشفير الفيديو. من فضلك، جرب مقطع فيديو مختلفًا أو اتصل بالمطورين.</string> + <string name="rcv_group_event_1_member_connected">%s متصل</string> + <string name="linked_desktops">أسطح المكتب المرتبطة</string> + <string name="v5_4_incognito_groups">مجموعات التخفي</string> + <string name="group_members_n">%s و%s و%d عضو</string> + <string name="this_device">هذا الجهاز</string> + <string name="moderated_items_description">%1$d من الرسائل يُشرف عليها بواسطة %2$s</string> + <string name="unblock_member_button">إلغاء حظر العضو</string> + <string name="remote_host_was_disconnected_toast"><![CDATA[جوّال <b>%s</b> قُطع اتصاله]]></string> + <string name="waiting_for_desktop">في انتظار سطح المكتب…</string> + <string name="v5_4_better_groups_descr">انضمام أسرع ورسائل أكثر موثوقية.</string> + <string name="linked_mobiles">الجوّالات المرتبطة</string> + <string name="contact_tap_to_connect">انقر للاتصال</string> + <string name="this_device_name">اسم هذا الجهاز</string> + <string name="connect_plan_you_are_already_in_group_vName"><![CDATA[أنت بالفعل في المجموعة <b>%1$s</b>.]]></string> + <string name="connect_plan_this_is_your_own_simplex_address">هذا هو عنوان SimpleX الخاص بك!</string> + <string name="loading_remote_file_title">جارِ تحميل الملف</string> + <string name="found_desktop">وجدت سطح المكتب</string> + <string name="alert_text_encryption_renegotiation_failed">فشلت إعادة التفاوض على التعمية.</string> + <string name="not_compatible">غير متوافق!</string> + <string name="link_a_mobile">ربط الجوّال</string> + <string name="remove_member_button">إزالة العضو</string> + <string name="unblock_member_question">إلغاء حظر العضو؟</string> + <string name="settings_section_title_use_from_desktop">استخدم من سطح المكتب</string> + <string name="session_code">رمز الجلسة</string> + <string name="connect_plan_repeat_join_request">هل تريد تكرار طلب الانضمام؟</string> + <string name="button_remove_member_question">إزالة العضو؟</string> + <string name="connect_plan_you_are_already_connecting_via_this_one_time_link">أنت متصل بالفعل عبر هذا الرابط لمرة واحدة!</string> + <string name="connect_plan_open_group">افتح المجموعة</string> + <string name="this_device_version"><![CDATA[<i>(هذا الجهاز v%s)</i>]]></string> + <string name="unlink_desktop">فك الربط</string> + <string name="unblock_member_desc">سيتم عرض الرسائل من %s!</string> + <string name="this_device_name_shared_with_mobile">ستتم مشاركة اسم الجهاز مع عميل الجوّال متصل.</string> + <string name="error_sending_message_contact_invitation">حدث خطأ أثناء إرسال الدعوة</string> + <string name="verify_code_on_mobile">تحقق من الرمز على الجوّال</string> + <string name="enter_this_device_name">أدخل اسم الجهاز هذا…</string> + <string name="error">خطأ</string> + <string name="non_content_uri_alert_text">لقد شاركت مسار ملف غير صالح. أبلغ عن المشكلة لمطوري التطبيق.</string> + <string name="invalid_name">اسم غير صالح!</string> + <string name="paste_desktop_address">لصق عنوان سطح المكتب</string> + <string name="connect_plan_this_is_your_link_for_group_vName"><![CDATA[هذا هو الرابط الخاص بك للمجموعة <b>%1$s</b>!]]></string> + <string name="verify_code_with_desktop">تحقق من الرمز مع سطح المكتب</string> + <string name="scan_qr_code_from_desktop">مسح رمز QR من سطح المكتب</string> + <string name="unblock_member_confirmation">إلغاء الحظر</string> + <string name="v5_4_more_things_descr">- إشعار اختياريًا جهات الاتصال المحذوفة. +\n- أسماء الملفات الشخصية بمسافات. +\n- و اكثر!</string> + <string name="non_content_uri_alert_title">مسار الملف غير صالح</string> + <string name="connect_plan_you_have_already_requested_connection_via_this_address">لقد طلبت بالفعل الاتصال عبر هذا العنوان!</string> + <string name="terminal_always_visible">إظهار وحدة التحكم في نافذة جديدة</string> + <string name="scan_from_mobile">المسح من الجوّال</string> + <string name="verify_connections">تحقق من الاتصالات</string> + <string name="loading_remote_file_desc">من فضلك، انتظر حتى يتم تحميل الملف من الجوّال المرتبط</string> + <string name="verify_connection">تحقق من الاتصال</string> + <string name="refresh_qr_code">أعِد التحميل</string> + <string name="random_port">عشوائي</string> + <string name="waiting_for_mobile_to_connect">في انتظار اتصال الجوال:</string> + <string name="open_port_in_firewall_desc">للسماح لتطبيق الجوال بالاتصال بسطح المكتب، افتح هذا المنفذ في جدار الحماية لديك، إذا فعلته</string> + <string name="create_chat_profile">أنشئ ملف تعريف الدردشة</string> + <string name="app_was_crashed">عرض التحطم</string> + <string name="open_port_in_firewall_title">فتح منفذ في جدار الحماية</string> + <string name="disconnect_remote_hosts">اقطع اتصال الجوالات</string> + <string name="no_connected_mobile">لا يوجد جوال متصل</string> + <string name="error_showing_content">خطأ في إظهار المحتوى</string> + <string name="error_showing_message">خطأ في إظهار الرسالة</string> + <string name="callstatus_ended">انتهت المكالمة %1$s</string> + <string name="you_can_make_address_visible_via_settings">يمكنك جعله مرئيًا لجهات اتصال SimpleX الخاصة بك عبر الإعدادات.</string> + <string name="recent_history_is_not_sent_to_new_members">لا يتم إرسال التاريخ إلى الأعضاء الجدد.</string> + <string name="retry_verb">حاول مجددًا</string> + <string name="camera_not_available">الكاميرا غير متوفرة</string> + <string name="enable_sending_recent_history">أرسل ما يصل إلى 100 رسالة أخيرة للأعضاء الجدد.</string> + <string name="add_contact_button_to_create_link_or_connect_via_link"><![CDATA[<b>إضافة جهة اتصال</b>: لإنشاء رابط دعوة جديد، أو الاتصال عبر رابط استلمته.]]></string> + <string name="disable_sending_recent_history">لا ترسل التاريخ للأعضاء الجدد.</string> + <string name="or_show_this_qr_code">أو أظهر هذا الرمز</string> + <string name="recent_history_is_sent_to_new_members">يتم إرسال ما يصل إلى 100 رسالة أخيرة إلى الأعضاء الجدد.</string> + <string name="code_you_scanned_is_not_simplex_link_qr_code">الرمز الذي مسحته ضوئيًا ليس رمز QR لرابط SimpleX.</string> + <string name="the_text_you_pasted_is_not_a_link">النص الذي لصقته ليس رابط SimpleX.</string> + <string name="enable_camera_access">فعّل الوصول إلى الكاميرا</string> + <string name="you_can_view_invitation_link_again">يمكنك عرض رابط الدعوة مرة أخرى في تفاصيل الاتصال.</string> + <string name="keep_unused_invitation_question">أبقِ الدعوة غير المستخدمة؟</string> + <string name="share_this_1_time_link">شارك رابط الدعوة هذا لمرة واحدة</string> + <string name="create_group_button_to_create_new_group"><![CDATA[<b>أنشِئ مجموعة</b>: لإنشاء مجموعة جديدة.]]></string> + <string name="recent_history">التاريخ المرئي</string> + <string name="la_app_passcode">رمز مرور التطبيق</string> + <string name="new_chat">دردشة جديدة</string> + <string name="loading_chats">جارِ تحميل الدردشات…</string> + <string name="creating_link">جارِ إنشاء الرابط…</string> + <string name="or_scan_qr_code">أو امسح رمز QR</string> + <string name="invalid_qr_code">رمز QR غير صالح</string> + <string name="add_contact_tab">أضِف جهة اتصال</string> + <string name="tap_to_scan">انقر للمسح الضوئي</string> + <string name="keep_invitation_link">أبقِ</string> + <string name="tap_to_paste_link">انقر للصق الرابط</string> + <string name="search_or_paste_simplex_link">ابحث أو ألصِق رابط SimpleX</string> + <string name="start_chat_question">بدء الدردشة؟</string> + <string name="chat_is_stopped_you_should_transfer_database">توقفت الدردشة. إذا كنت قد استخدمت قاعدة البيانات هذه بالفعل على جهاز آخر، فيجب عليك نقلها مرة أخرى قبل بدء الدردشة.</string> + <string name="show_internal_errors">اعرض الأخطاء الداخلية</string> + <string name="agent_critical_error_title">خطأ فادح</string> + <string name="agent_internal_error_title">خطأ داخلي</string> + <string name="agent_internal_error_desc">يُرجى إبلاغ المطورين بذلك: +\n%s</string> + <string name="agent_critical_error_desc">يُرجى إبلاغ المطورين بذلك: +\n%s +\n +\nيوصى بإعادة تشغيل التطبيق.</string> + <string name="restart_chat_button">أعد تشغيل الدردشة</string> + <string name="remote_host_error_inactive"><![CDATA[الجوال <b>%s</b> غير نشط]]></string> + <string name="show_slow_api_calls">أظهر مكالمات API البطيئة</string> + <string name="group_member_status_unknown_short">غير معروف</string> + <string name="profile_update_event_updated_profile">حدّثت الملف الشخصي</string> + <string name="remote_host_error_missing"><![CDATA[الجوال <b>%s</b> مفقود]]></string> + <string name="remote_host_error_bad_version"><![CDATA[الجوال <b>%s</b> لديه إصدار غير مدعوم. يُرجى التأكد من استخدام نفس الإصدار على كلا الجهازين]]></string> + <string name="remote_host_error_bad_state"><![CDATA[الاتصال بالجوال <b>%s</b> في حالة سيئة]]></string> + <string name="failed_to_create_user_invalid_title">اسم العرض غير صالح!</string> + <string name="failed_to_create_user_invalid_desc">اسم العرض هذا غير صالح. الرجاء اختيار اسم آخر.</string> + <string name="remote_host_was_disconnected_title">توقف الاتصال</string> + <string name="remote_ctrl_was_disconnected_title">توقف الاتصال</string> + <string name="remote_host_disconnected_from"><![CDATA[قُطع الاتصال بالجوال <b>%s</b> بسبب: %s]]></string> + <string name="remote_ctrl_disconnected_with_reason">قُطع الاتصال بسبب: %s</string> + <string name="remote_host_error_disconnected"><![CDATA[قُطع اتصال الجوال <b>%s</b>]]></string> + <string name="remote_host_error_timeout"><![CDATA[انتهت المهلة أثناء الاتصال بالجوال <b>%s</b>]]></string> + <string name="remote_ctrl_error_inactive">سطح المكتب غير نشط</string> + <string name="remote_host_error_busy"><![CDATA[الجوال <b>%s</b> مشغول]]></string> + <string name="remote_ctrl_error_timeout">انتهت المهلة أثناء الاتصال بسطح المكتب</string> + <string name="remote_ctrl_error_disconnected">قُطع اتصال سطح المكتب</string> + <string name="remote_ctrl_error_bad_state">الاتصال بسطح المكتب في حالة سيئة</string> + <string name="remote_ctrl_error_bad_invitation">يحتوي سطح المكتب على رمز دعوة خاطئ</string> + <string name="remote_ctrl_error_busy">سطح المكتب مشغول</string> + <string name="remote_ctrl_error_bad_version">يحتوي سطح المكتب على إصدار غير مدعوم. يُرجى التأكد من استخدام نفس الإصدار على كلا الجهازين</string> + <string name="past_member_vName">العضو السابق %1$s</string> + <string name="possible_deadlock_title">مأزق</string> + <string name="possible_deadlock_desc">يستغرق تنفيذ التعليمات البرمجية وقتًا طويلاً جدًا: %1$d ثانية. من المحتمل أن التطبيق مجمّد: %2$s</string> + <string name="possible_slow_function_title">وظيفة بطيئة</string> + <string name="developer_options_section">خيارات المطور</string> + <string name="profile_update_event_member_name_changed">تغيّر العضو %1$s إلى %2$s</string> + <string name="profile_update_event_removed_address">أزلت عنوان الاتصال</string> + <string name="profile_update_event_removed_picture">أزلت الصورة الشخصية</string> + <string name="profile_update_event_set_new_address">عيّن عنوان جهة اتصال جديد</string> + <string name="profile_update_event_set_new_picture">عيّن صورة شخصية جديدة</string> + <string name="group_member_status_unknown">حالة غير معروفة</string> + <string name="profile_update_event_contact_name_changed">تغيّر جهة الاتصال %1$s إلى %2$s</string> + <string name="possible_slow_function_desc">يستغرق تنفيذ الوظيفة وقتًا طويلاً جدًا: %1$d ثانية: %2$s</string> + <string name="v5_5_private_notes">ملاحظات خاصة</string> + <string name="v5_5_join_group_conversation">انضم إلى المحادثات الجماعية</string> + <string name="v5_5_simpler_connect_ui_descr">يقبل شريط البحث روابط الدعوة.</string> + <string name="v5_5_message_delivery">تحسّن تسليم الرسائل</string> + <string name="v5_5_message_delivery_descr">مع انخفاض استخدام البطارية.</string> + <string name="clear_note_folder_warning">سيتم حذف كافة الرسائل - لا يمكن التراجع عن هذا!</string> + <string name="info_row_created_at">أُنشئ في</string> + <string name="v5_5_new_interface_languages">واجهة المستخدم المجرية والتركية</string> + <string name="v5_5_simpler_connect_ui">الصق الرابط للاتصال!</string> + <string name="v5_5_join_group_conversation_descr">التاريخ الحديث وبوت الدليل المحسن.</string> + <string name="v5_5_private_notes_descr">مع الملفات والوسائط المُعمّاة.</string> + <string name="error_creating_message">حدث خطأ أثناء إنشاء الرسالة</string> + <string name="error_deleting_note_folder">حدث خطأ أثناء حذف الملاحظات الخاصة</string> + <string name="note_folder_local_display_name">ملاحظات خاصة</string> + <string name="clear_note_folder_question">مسح الملاحظات الخاصة؟</string> + <string name="share_text_created_at">أُنشئ في: %s</string> + <string name="saved_message_title">رسالة محفوظة</string> + <string name="unblock_for_all_question">إلغاء حظر العضو للجميع؟</string> + <string name="unblock_for_all">إلغاء الحظر للجميع</string> + <string name="error_blocking_member_for_all">حدث خطأ أثناء حظر العضو للجميع</string> + <string name="blocked_by_admin_items_description">حُظر %d رسالة من قبل المشرف</string> + <string name="rcv_group_event_member_blocked">محظور %s</string> + <string name="rcv_group_event_member_unblocked">أُلغيت حظر %s</string> + <string name="snd_group_event_member_blocked">حظرت %s</string> + <string name="snd_group_event_member_unblocked">أُلغيت حظر %s</string> + <string name="member_info_member_blocked">محظور</string> + <string name="block_for_all">حظر للجميع</string> + <string name="block_for_all_question">حظر العضو للجميع؟</string> + <string name="blocked_by_admin_item_description">محظور من قبل المشرف</string> + <string name="member_blocked_by_admin">محظور من قبل المشرف</string> </resources> \ No newline at end of file diff --git a/apps/multiplatform/common/src/commonMain/resources/MR/base/strings.xml b/apps/multiplatform/common/src/commonMain/resources/MR/base/strings.xml index d13a7c65fb..d36eca273e 100644 --- a/apps/multiplatform/common/src/commonMain/resources/MR/base/strings.xml +++ b/apps/multiplatform/common/src/commonMain/resources/MR/base/strings.xml @@ -33,9 +33,11 @@ <string name="marked_deleted_description">marked deleted</string> <string name="marked_deleted_items_description">%d messages marked deleted</string> <string name="moderated_item_description">moderated by %s</string> - <string name="moderated_items_description">%d messages moderated by %s</string> + <string name="moderated_items_description">%1$d messages moderated by %2$s</string> <string name="blocked_item_description">blocked</string> + <string name="blocked_by_admin_item_description">blocked by admin</string> <string name="blocked_items_description">%d messages blocked</string> + <string name="blocked_by_admin_items_description">%d messages blocked by admin</string> <string name="sending_files_not_yet_supported">sending files is not supported yet</string> <string name="receiving_files_not_yet_supported">receiving files is not supported yet</string> <string name="sender_you_pronoun">you</string> @@ -51,6 +53,9 @@ <string name="decryption_error">Decryption error</string> <string name="encryption_renegotiation_error">Encryption re-negotiation error</string> + <!-- NoteFolder - ChatModel.kt --> + <string name="note_folder_local_display_name">Private notes</string> + <!-- PendingContactConnection - ChatModel.kt --> <string name="connection_local_display_name">connection %1$d</string> <string name="display_name_connection_established">connection established</string> @@ -90,6 +95,8 @@ <string name="failed_to_create_user_title">Error creating profile!</string> <string name="failed_to_create_user_duplicate_title">Duplicate display name!</string> <string name="failed_to_create_user_duplicate_desc">You already have a chat profile with the same display name. Please choose another name.</string> + <string name="failed_to_create_user_invalid_title">Invalid display name!</string> + <string name="failed_to_create_user_invalid_desc">This display name is invalid. Please choose another name.</string> <string name="failed_to_active_user_title">Error switching profile!</string> <!-- API Error Responses - SimpleXAPI.kt --> @@ -97,6 +104,7 @@ <string name="connection_error">Connection error</string> <string name="network_error_desc">Please check your network connection with %1$s and try again.</string> <string name="error_sending_message">Error sending message</string> + <string name="error_creating_message">Error creating message</string> <string name="error_loading_details">Error loading details</string> <string name="error_adding_members">Error adding member(s)</string> <string name="error_joining_group">Error joining group</string> @@ -114,6 +122,7 @@ <string name="sender_may_have_deleted_the_connection_request">Sender may have deleted the connection request.</string> <string name="error_deleting_contact">Error deleting contact</string> <string name="error_deleting_group">Error deleting group</string> + <string name="error_deleting_note_folder">Error deleting private notes</string> <string name="error_deleting_contact_request">Error deleting contact request</string> <string name="error_deleting_pending_contact_connection">Error deleting pending contact connection</string> <string name="error_changing_address">Error changing address</string> @@ -137,6 +146,10 @@ <string name="smp_server_test_delete_file">Delete file</string> <string name="error_deleting_user">Error deleting user profile</string> <string name="error_updating_user_privacy">Error updating user privacy</string> + <string name="possible_deadlock_title">Deadlock</string> + <string name="possible_deadlock_desc">Execution of code takes too long time: %1$d seconds. Probably, the app is frozen: %2$s</string> + <string name="possible_slow_function_title">Slow function</string> + <string name="possible_slow_function_desc">Execution of function takes too long time: %1$d seconds: %2$s</string> <!-- background service notice - SimpleXAPI.kt --> <string name="icon_descr_instant_notifications">Instant notifications</string> @@ -293,9 +306,11 @@ <string name="tap_to_start_new_chat">Tap to start a new chat</string> <string name="chat_with_developers">Chat with the developers</string> <string name="you_have_no_chats">You have no chats</string> + <string name="loading_chats">Loading chats…</string> <string name="no_filtered_chats">No filtered chats</string> <string name="contact_tap_to_connect">Tap to Connect</string> <string name="connect_with_contact_name_question">Connect with %1$s?</string> + <string name="search_or_paste_simplex_link">Search or paste SimpleX link</string> <!-- ChatView.kt --> <string name="no_selected_chat">No selected chat</string> @@ -427,6 +442,11 @@ <string name="connect_via_link_or_qr_from_clipboard_or_in_person">(scan or paste from clipboard)</string> <string name="only_stored_on_members_devices">(only stored by group members)</string> + <!-- QRCodeScanner --> + <string name="enable_camera_access">Enable camera access</string> + <string name="tap_to_scan">Tap to scan</string> + <string name="camera_not_available">Camera not available</string> + <!-- GetImageView --> <string name="toast_permission_denied">Permission Denied!</string> <string name="use_camera_button">Camera</string> @@ -442,8 +462,8 @@ <string name="to_start_a_new_chat_help_header">To start a new chat</string> <string name="chat_help_tap_button">Tap button</string> <string name="above_then_preposition_continuation">above, then:</string> - <string name="add_new_contact_to_create_one_time_QR_code"><![CDATA[<b>Add new contact</b>: to create your one-time QR Code for your contact.]]></string> - <string name="scan_QR_code_to_connect_to_contact_who_shows_QR_code"><![CDATA[<b>Scan QR code</b>: to connect to your contact who shows QR code to you.]]></string> + <string name="add_contact_button_to_create_link_or_connect_via_link"><![CDATA[<b>Add contact</b>: to create a new invitation link, or connect via a link you received.]]></string> + <string name="create_group_button_to_create_new_group"><![CDATA[<b>Create group</b>: to create a new group.]]></string> <string name="to_connect_via_link_title">To connect via link</string> <string name="if_you_received_simplex_invitation_link_you_can_open_in_browser">If you received SimpleX Chat invitation link, you can open it in your browser:</string> <string name="desktop_scan_QR_code_from_app_via_scan_QR_code"><![CDATA[💻 desktop: scan displayed QR code from the app, via <b>Scan QR code</b>.]]></string> @@ -458,7 +478,9 @@ <!-- Clear Chat - ChatListNavLinkView.kt --> <string name="clear_chat_question">Clear chat?</string> + <string name="clear_note_folder_question">Clear private notes?</string> <string name="clear_chat_warning">All messages will be deleted - this cannot be undone! The messages will be deleted ONLY for you.</string> + <string name="clear_note_folder_warning">All messages will be deleted - this cannot be undone!</string> <string name="clear_verb">Clear</string> <string name="clear_chat_button">Clear chat</string> <string name="clear_chat_menu_action">Clear</string> @@ -546,11 +568,26 @@ <string name="this_string_is_not_a_connection_link">This string is not a connection link!</string> <string name="you_can_also_connect_by_clicking_the_link"><![CDATA[You can also connect by clicking the link. If it opens in the browser, click <b>Open in mobile app</b> button.]]></string> - <!-- CreateLinkView.kt --> - <string name="create_one_time_link">Create one-time invitation link</string> + <!-- NewChatView.kt --> + <string name="new_chat">New chat</string> + <string name="add_contact_tab">Add contact</string> <string name="one_time_link">One-time invitation link</string> <string name="one_time_link_short">1-time link</string> <string name="simplex_address">SimpleX address</string> + <string name="or_show_this_qr_code">Or show this code</string> + <string name="or_scan_qr_code">Or scan QR code</string> + <string name="keep_unused_invitation_question">Keep unused invitation?</string> + <string name="you_can_view_invitation_link_again">You can view invitation link again in connection details.</string> + <string name="keep_invitation_link">Keep</string> + <string name="creating_link">Creating link…</string> + <string name="retry_verb">Retry</string> + <string name="share_this_1_time_link">Share this 1-time invite link</string> + <string name="paste_the_link_you_received">Paste the link you received</string> + <string name="the_text_you_pasted_is_not_a_link">The text you pasted is not a SimpleX link.</string> + <string name="tap_to_paste_link">Tap to paste link</string> + + <string name="invalid_qr_code">Invalid QR code</string> + <string name="code_you_scanned_is_not_simplex_link_qr_code">The code you scanned is not a SimpleX link QR code.</string> <!-- ScanCodeView.kt --> <string name="scan_code">Scan code</string> @@ -662,7 +699,9 @@ <string name="hide_dev_options">Hide:</string> <string name="show_developer_options">Show developer options</string> <string name="developer_options">Database IDs and Transport isolation option.</string> + <string name="developer_options_section">Developer options</string> <string name="show_internal_errors">Show internal errors</string> + <string name="show_slow_api_calls">Show slow API calls</string> <string name="shutdown_alert_question">Shutdown?</string> <string name="shutdown_alert_desc">Notifications will stop working until you re-launch the app</string> @@ -800,9 +839,6 @@ <string name="you_can_change_it_later">Random passphrase is stored in settings as plaintext.\nYou can change it later.</string> <string name="use_random_passphrase">Use random passphrase</string> - <!-- MakeConnection --> - <string name="paste_the_link_you_received">Paste received link</string> - <!-- Call --> <string name="incoming_video_call">Incoming video call</string> <string name="incoming_audio_call">Incoming audio call</string> @@ -898,6 +934,7 @@ <string name="authentication_cancelled">Authentication cancelled</string> <string name="la_mode_system">System</string> <string name="la_mode_passcode">Passcode</string> + <string name="la_app_passcode">App passcode</string> <string name="la_mode_off">Off</string> <string name="passcode_set">Passcode set!</string> <string name="passcode_changed">Passcode changed!</string> @@ -1093,6 +1130,8 @@ <!-- ChatModel.chatRunning interactions --> <string name="chat_is_stopped_indication">Chat is stopped</string> <string name="you_can_start_chat_via_setting_or_by_restarting_the_app">You can start chat via app Settings / Database or by restarting the app.</string> + <string name="start_chat_question">Start chat?</string> + <string name="chat_is_stopped_you_should_transfer_database">Chat is stopped. If you already used this database on another device, you should transfer it back before starting chat.</string> <!-- ChatArchiveView.kt --> <string name="chat_archive_header">Chat archive</string> @@ -1139,6 +1178,8 @@ <string name="rcv_group_event_member_connected">connected</string> <string name="rcv_group_event_member_left">left</string> <string name="rcv_group_event_changed_member_role">changed role of %s to %s</string> + <string name="rcv_group_event_member_blocked">blocked %s</string> + <string name="rcv_group_event_member_unblocked">unblocked %s</string> <string name="rcv_group_event_changed_your_role">changed your role to %s</string> <string name="rcv_group_event_member_deleted">removed %1$s</string> <string name="rcv_group_event_user_deleted">removed you</string> @@ -1148,6 +1189,8 @@ <string name="rcv_group_event_member_created_contact">connected directly</string> <string name="snd_group_event_changed_member_role">you changed role of %s to %s</string> <string name="snd_group_event_changed_role_for_yourself">you changed role for yourself to %s</string> + <string name="snd_group_event_member_blocked">you blocked %s</string> + <string name="snd_group_event_member_unblocked">you unblocked %s</string> <string name="snd_group_event_member_deleted">you removed %1$s</string> <string name="snd_group_event_user_left">you left</string> <string name="snd_group_event_group_profile_updated">group profile updated</string> @@ -1163,6 +1206,15 @@ <string name="rcv_group_event_open_chat">Open</string> + <!-- Profile update event chat items --> + <string name="profile_update_event_contact_name_changed">contact %1$s changed to %2$s</string> + <string name="profile_update_event_removed_picture">removed profile picture</string> + <string name="profile_update_event_set_new_picture">set new profile picture</string> + <string name="profile_update_event_removed_address">removed contact address</string> + <string name="profile_update_event_set_new_address">set new contact address</string> + <string name="profile_update_event_updated_profile">updated profile</string> + <string name="profile_update_event_member_name_changed">member %1$s changed to %2$s</string> + <!-- Conn event chat items --> <string name="rcv_conn_event_switch_queue_phase_completed">changed address for you</string> <string name="rcv_conn_event_switch_queue_phase_changing">changing address…</string> @@ -1193,6 +1245,7 @@ <string name="group_member_status_removed">removed</string> <string name="group_member_status_left">left</string> <string name="group_member_status_group_deleted">group deleted</string> + <string name="group_member_status_unknown">unknown status</string> <string name="group_member_status_invited">invited</string> <string name="group_member_status_introduced">connecting (introduced)</string> <string name="group_member_status_intro_invitation">connecting (introduction invitation)</string> @@ -1203,6 +1256,9 @@ <string name="group_member_status_creator">creator</string> <string name="group_member_status_connecting">connecting</string> + <string name="group_member_status_unknown_short">unknown</string> + + <string name="past_member_vName">Past member %1$s</string> <!-- AddGroupMembersView.kt --> <string name="no_contacts_to_add">No contacts to add</string> @@ -1258,6 +1314,7 @@ <string name="info_row_database_id">Database ID</string> <string name="info_row_updated_at">Record updated at</string> <string name="info_row_sent_at">Sent at</string> + <string name="info_row_created_at">Created at</string> <string name="info_row_received_at">Received at</string> <string name="info_row_deleted_at">Deleted at</string> <string name="info_row_moderated_at">Moderated at</string> @@ -1265,6 +1322,7 @@ <string name="share_text_database_id">Database ID: %d</string> <string name="share_text_updated_at">Record updated at: %s</string> <string name="share_text_sent_at">Sent at: %s</string> + <string name="share_text_created_at">Created at: %s</string> <string name="share_text_received_at">Received at: %s</string> <string name="share_text_deleted_at">Deleted at: %s</string> <string name="share_text_moderated_at">Moderated at: %s</string> @@ -1274,6 +1332,7 @@ <string name="current_version_timestamp">%s (current)</string> <string name="item_info_no_text">no text</string> <string name="recipient_colon_delivery_status">%s: %s</string> + <string name="saved_message_title">Saved message</string> <!-- GroupMemberInfoView.kt --> <string name="button_remove_member_question">Remove member?</string> @@ -1286,11 +1345,17 @@ <string name="block_member_question">Block member?</string> <string name="block_member_button">Block member</string> <string name="block_member_confirmation">Block</string> + <string name="block_for_all_question">Block member for all?</string> + <string name="block_for_all">Block for all</string> <string name="block_member_desc">All new messages from %s will be hidden!</string> <string name="unblock_member_question">Unblock member?</string> <string name="unblock_member_button">Unblock member</string> <string name="unblock_member_confirmation">Unblock</string> + <string name="unblock_for_all_question">Unblock member for all?</string> + <string name="unblock_for_all">Unblock for all</string> <string name="unblock_member_desc">Messages from %s will be shown!</string> + <string name="member_blocked_by_admin">Blocked by admin</string> + <string name="member_info_member_blocked">blocked</string> <string name="member_info_section_title_member">MEMBER</string> <string name="role_in_group">Role</string> <string name="change_role">Change role</string> @@ -1303,6 +1368,7 @@ <string name="connect_via_member_address_alert_desc">Сonnection request will be sent to this group member.</string> <string name="error_removing_member">Error removing member</string> <string name="error_changing_role">Error changing role</string> + <string name="error_blocking_member_for_all">Error blocking member for all</string> <string name="info_row_group">Group</string> <string name="info_row_connection">Connection</string> <string name="conn_level_desc_direct">direct</string> @@ -1370,9 +1436,6 @@ <string name="user_unmute">Unmute</string> <string name="enter_password_to_show">Enter password in search</string> <string name="tap_to_activate_profile">Tap to activate profile.</string> - <string name="cant_delete_user_profile">Can\'t delete user profile!</string> - <string name="should_be_at_least_one_visible_profile">There should be at least one visible user profile.</string> - <string name="should_be_at_least_one_profile">There should be at least one user profile.</string> <string name="make_profile_private">Make profile private!</string> <string name="you_can_hide_or_mute_user_profile">You can hide or mute a user profile - hold it for the menu.</string> <string name="dont_show_again">Don\'t show again</string> @@ -1440,6 +1503,7 @@ <string name="message_reactions">Message reactions</string> <string name="voice_messages">Voice messages</string> <string name="files_and_media">Files and media</string> + <string name="recent_history">Visible history</string> <string name="audio_video_calls">Audio/video calls</string> <string name="available_in_v51">\nAvailable in v5.1</string> <string name="feature_enabled">enabled</string> @@ -1452,8 +1516,8 @@ <string name="allow_your_contacts_to_send_disappearing_messages">Allow your contacts to send disappearing messages.</string> <string name="allow_disappearing_messages_only_if">Allow disappearing messages only if your contact allows them.</string> <string name="prohibit_sending_disappearing_messages">Prohibit sending disappearing messages.</string> - <string name="allow_your_contacts_irreversibly_delete">Allow your contacts to irreversibly delete sent messages.</string> - <string name="allow_irreversible_message_deletion_only_if">Allow irreversible message deletion only if your contact allows it to you.</string> + <string name="allow_your_contacts_irreversibly_delete">Allow your contacts to irreversibly delete sent messages. (24 hours)</string> + <string name="allow_irreversible_message_deletion_only_if">Allow irreversible message deletion only if your contact allows it to you. (24 hours)</string> <string name="contacts_can_mark_messages_for_deletion">Contacts can mark messages for deletion; you will be able to view them.</string> <string name="allow_your_contacts_to_send_voice_messages">Allow your contacts to send voice messages.</string> <string name="allow_voice_messages_only_if">Allow voice messages only if your contact allows them.</string> @@ -1468,9 +1532,9 @@ <string name="only_you_can_send_disappearing">Only you can send disappearing messages.</string> <string name="only_your_contact_can_send_disappearing">Only your contact can send disappearing messages.</string> <string name="disappearing_prohibited_in_this_chat">Disappearing messages are prohibited in this chat.</string> - <string name="both_you_and_your_contacts_can_delete">Both you and your contact can irreversibly delete sent messages.</string> - <string name="only_you_can_delete_messages">Only you can irreversibly delete messages (your contact can mark them for deletion).</string> - <string name="only_your_contact_can_delete">Only your contact can irreversibly delete messages (you can mark them for deletion).</string> + <string name="both_you_and_your_contacts_can_delete">Both you and your contact can irreversibly delete sent messages. (24 hours)</string> + <string name="only_you_can_delete_messages">Only you can irreversibly delete messages (your contact can mark them for deletion). (24 hours)</string> + <string name="only_your_contact_can_delete">Only your contact can irreversibly delete messages (you can mark them for deletion). (24 hours)</string> <string name="message_deletion_prohibited">Irreversible message deletion is prohibited in this chat.</string> <string name="both_you_and_your_contact_can_send_voice">Both you and your contact can send voice messages.</string> <string name="only_you_can_send_voice">Only you can send voice messages.</string> @@ -1488,7 +1552,7 @@ <string name="prohibit_sending_disappearing">Prohibit sending disappearing messages.</string> <string name="allow_direct_messages">Allow sending direct messages to members.</string> <string name="prohibit_direct_messages">Prohibit sending direct messages to members.</string> - <string name="allow_to_delete_messages">Allow to irreversibly delete sent messages.</string> + <string name="allow_to_delete_messages">Allow to irreversibly delete sent messages. (24 hours)</string> <string name="prohibit_message_deletion">Prohibit irreversible message deletion.</string> <string name="allow_to_send_voice">Allow to send voice messages.</string> <string name="prohibit_sending_voice">Prohibit sending voice messages.</string> @@ -1496,11 +1560,13 @@ <string name="prohibit_message_reactions_group">Prohibit messages reactions.</string> <string name="allow_to_send_files">Allow to send files and media.</string> <string name="prohibit_sending_files">Prohibit sending files and media.</string> + <string name="enable_sending_recent_history">Send up to 100 last messages to new members.</string> + <string name="disable_sending_recent_history">Do not send history to new members.</string> <string name="group_members_can_send_disappearing">Group members can send disappearing messages.</string> <string name="disappearing_messages_are_prohibited">Disappearing messages are prohibited in this group.</string> <string name="group_members_can_send_dms">Group members can send direct messages.</string> <string name="direct_messages_are_prohibited_in_chat">Direct messages between members are prohibited in this group.</string> - <string name="group_members_can_delete">Group members can irreversibly delete sent messages.</string> + <string name="group_members_can_delete">Group members can irreversibly delete sent messages. (24 hours)</string> <string name="message_deletion_prohibited_in_chat">Irreversible message deletion is prohibited in this group.</string> <string name="group_members_can_send_voice">Group members can send voice messages.</string> <string name="voice_messages_are_prohibited">Voice messages are prohibited in this group.</string> @@ -1508,6 +1574,8 @@ <string name="message_reactions_are_prohibited">Message reactions are prohibited in this group.</string> <string name="group_members_can_send_files">Group members can send files and media.</string> <string name="files_are_prohibited_in_group">Files and media are prohibited in this group.</string> + <string name="recent_history_is_sent_to_new_members">Up to 100 last messages are sent to new members.</string> + <string name="recent_history_is_not_sent_to_new_members">History is not sent to new members.</string> <string name="delete_after">Delete after</string> <string name="ttl_sec">%d sec</string> <string name="ttl_s">%ds</string> @@ -1624,6 +1692,15 @@ <string name="v5_4_block_group_members">Block group members</string> <string name="v5_4_block_group_members_descr">To hide unwanted messages.</string> <string name="v5_4_more_things_descr">- optionally notify deleted contacts.\n- profile names with spaces.\n- and more!</string> + <string name="v5_5_private_notes">Private notes</string> + <string name="v5_5_private_notes_descr">With encrypted files and media.</string> + <string name="v5_5_simpler_connect_ui">Paste link to connect!</string> + <string name="v5_5_simpler_connect_ui_descr">Search bar accepts invitation links.</string> + <string name="v5_5_join_group_conversation">Join group conversations</string> + <string name="v5_5_join_group_conversation_descr">Recent history and improved directory bot.</string> + <string name="v5_5_message_delivery">Improved message delivery</string> + <string name="v5_5_message_delivery_descr">With reduced battery usage.</string> + <string name="v5_5_new_interface_languages">Hungarian and Turkish UI</string> <!-- CustomTimePicker --> <string name="custom_time_unit_seconds">seconds</string> @@ -1667,6 +1744,10 @@ <string name="disconnect_remote_host">Disconnect</string> <string name="disconnect_remote_hosts">Disconnect mobiles</string> <string name="remote_host_was_disconnected_toast"><![CDATA[Mobile <b>%s</b> was disconnected]]></string> + <string name="remote_host_was_disconnected_title">Connection stopped</string> + <string name="remote_ctrl_was_disconnected_title">Connection stopped</string> + <string name="remote_host_disconnected_from"><![CDATA[Disconnected from mobile <b>%s</b> with the reason: %s]]></string> + <string name="remote_ctrl_disconnected_with_reason">Disconnected with the reason: %s</string> <string name="disconnect_desktop_question">Disconnect desktop?</string> <string name="only_one_device_can_work_at_the_same_time">Only one device can work at the same time</string> <string name="open_on_mobile_and_scan_qr_code"><![CDATA[Open <i>Use from desktop</i> in mobile app and scan QR code.]]></string> @@ -1701,6 +1782,20 @@ <string name="random_port">Random</string> <string name="open_port_in_firewall_title">Open port in firewall</string> <string name="open_port_in_firewall_desc">To allow a mobile app to connect to the desktop, open this port in your firewall, if you have it enabled</string> + <string name="remote_host_error_missing"><![CDATA[Mobile <b>%s</b> is missing]]></string> + <string name="remote_host_error_inactive"><![CDATA[Mobile <b>%s</b> is inactive]]></string> + <string name="remote_host_error_busy"><![CDATA[Mobile <b>%s</b> is busy]]></string> + <string name="remote_host_error_timeout"><![CDATA[Timeout reached while connecting to the mobile <b>%s</b>]]></string> + <string name="remote_host_error_bad_state"><![CDATA[Connection to the mobile <b>%s</b> is in a bad state]]></string> + <string name="remote_host_error_bad_version"><![CDATA[Mobile <b>%s</b> has an unsupported version. Please, make sure you use the same version on both devices]]></string> + <string name="remote_host_error_disconnected"><![CDATA[Mobile <b>%s</b> was disconnected]]></string> + <string name="remote_ctrl_error_inactive">Desktop is inactive</string> + <string name="remote_ctrl_error_bad_state">Connection to the desktop is in a bad state</string> + <string name="remote_ctrl_error_busy">Desktop is busy</string> + <string name="remote_ctrl_error_timeout">Timeout reached while connecting to the desktop</string> + <string name="remote_ctrl_error_disconnected">Desktop was disconnected</string> + <string name="remote_ctrl_error_bad_invitation">Desktop has wrong invitation code</string> + <string name="remote_ctrl_error_bad_version">Desktop has an unsupported version. Please, make sure you use the same version on both devices</string> <!-- Under development --> <string name="in_developing_title">Coming soon!</string> @@ -1709,21 +1804,21 @@ <!-- Connection plan --> <string name="connect_plan_connect_to_yourself">Connect to yourself?</string> <string name="connect_plan_this_is_your_own_one_time_link">This is your own one-time link!</string> - <string name="connect_plan_you_are_already_connecting_to_vName">You are already connecting to %1$s.</string> + <string name="connect_plan_you_are_already_connecting_to_vName"><![CDATA[You are already connecting to <b>%1$s</b>.]]></string> <string name="connect_plan_already_connecting">Already connecting!</string> <string name="connect_plan_you_are_already_connecting_via_this_one_time_link">You are already connecting via this one-time link!</string> <string name="connect_plan_this_is_your_own_simplex_address">This is your own SimpleX address!</string> <string name="connect_plan_repeat_connection_request">Repeat connection request?</string> <string name="connect_plan_you_have_already_requested_connection_via_this_address">You have already requested connection via this address!</string> <string name="connect_plan_join_your_group">Join your group?</string> - <string name="connect_plan_this_is_your_link_for_group_vName">This is your link for group %1$s!</string> + <string name="connect_plan_this_is_your_link_for_group_vName"><![CDATA[This is your link for group <b>%1$s</b>!]]></string> <string name="connect_plan_open_group">Open group</string> <string name="connect_plan_repeat_join_request">Repeat join request?</string> <string name="connect_plan_group_already_exists">Group already exists!</string> - <string name="connect_plan_you_are_already_joining_the_group_vName">You are already joining the group %1$s.</string> + <string name="connect_plan_you_are_already_joining_the_group_vName"><![CDATA[You are already joining the group <b>%1$s</b>.]]></string> <string name="connect_plan_already_joining_the_group">Already joining the group!</string> <string name="connect_plan_you_are_already_joining_the_group_via_this_link">You are already joining the group via this link.</string> - <string name="connect_plan_you_are_already_in_group_vName">You are already in group %1$s.</string> + <string name="connect_plan_you_are_already_in_group_vName"><![CDATA[You are already in group <b>%1$s</b>.]]></string> <string name="connect_plan_connect_via_link">Connect via link?</string> <!-- Errors --> diff --git a/apps/multiplatform/common/src/commonMain/resources/MR/bg/strings.xml b/apps/multiplatform/common/src/commonMain/resources/MR/bg/strings.xml index c999d9b952..05101075a0 100644 --- a/apps/multiplatform/common/src/commonMain/resources/MR/bg/strings.xml +++ b/apps/multiplatform/common/src/commonMain/resources/MR/bg/strings.xml @@ -73,7 +73,7 @@ <string name="allow_verb">Позволи</string> <string name="clear_chat_warning">Всички съобщения ще бъдат изтрити - това не може да бъде отменено! Съобщенията ще бъдат изтрити САМО за вас.</string> <string name="allow_calls_only_if">Позволи обаждания само ако вашият контакт ги разрешава.</string> - <string name="allow_irreversible_message_deletion_only_if">Позволи необратимо изтриване на съобщение само ако вашият контакт го рарешава.</string> + <string name="allow_irreversible_message_deletion_only_if">Позволи необратимо изтриване на съобщение само ако вашият контакт го рарешава. (24 часа)</string> <string name="allow_message_reactions_only_if">Позволи реакции на съобщения само ако вашият контакт ги разрешава.</string> <string name="allow_to_send_disappearing">Позволи изпращане на изчезващи съобщения.</string> <string name="allow_voice_messages_only_if">Позволи гласови съобщения само ако вашият контакт ги разрешава.</string> @@ -95,7 +95,7 @@ <string name="v4_6_audio_video_calls">Аудио и видео разговори</string> <string name="audio_call_no_encryption">аудио разговор (не е e2e криптиран)</string> <string name="la_auth_failed">Неуспешна идентификация</string> - <string name="both_you_and_your_contacts_can_delete">И вие, и вашият контакт можете да изтриете необратимо изпратените съобщения.</string> + <string name="both_you_and_your_contacts_can_delete">И вие, и вашият контакт можете да изтриете необратимо изпратените съобщения. (24 часа)</string> <string name="auth_unavailable">Идентификацията е недостъпна</string> <string name="both_you_and_your_contact_can_add_message_reactions">И вие, и вашият контакт можете да добавяте реакции към съобщението.</string> <string name="impossible_to_recover_passphrase"><![CDATA[<b>Моля, обърнете внимание</b>: НЯМА да можете да възстановите или промените паролата, ако я загубите.]]></string> @@ -119,8 +119,6 @@ <string name="back">Назад</string> <string name="cancel_verb">Отказ</string> <string name="icon_descr_cancel_live_message">Спри живото съобщение</string> - <string name="add_new_contact_to_create_one_time_QR_code"><![CDATA[<b>Добави нов контакт</b>: за да създадете своя еднократен QR код за вашия контакт.]]></string> - <string name="scan_QR_code_to_connect_to_contact_who_shows_QR_code"><![CDATA[<b>Сканирай QR код</b>: за да се свържете с вашия контакт, който ви показва QR код.]]></string> <string name="use_camera_button">Камера</string> <string name="if_you_cant_meet_in_person">Ако не можете да се срещнете лично, покажете QR код във видеоразговора или споделете линка.</string> <string name="icon_descr_cancel_link_preview">спри визуализацията на линка</string> @@ -187,9 +185,8 @@ <string name="change_verb">Промени</string> <string name="change_member_role_question">Промяна на груповата роля\?</string> <string name="you_will_still_receive_calls_and_ntfs">Все още ще получавате обаждания и известия от заглушени профили, когато са активни.</string> - <string name="cant_delete_user_profile">Потребителският профил не може да се изтрие!</string> <string name="allow_disappearing_messages_only_if">Позволи изчезващи съобщения само ако вашият контакт ги разрешава.</string> - <string name="allow_your_contacts_irreversibly_delete">Позволи на вашите контакти да изтриват необратимо изпратените съобщения.</string> + <string name="allow_your_contacts_irreversibly_delete">Позволи на вашите контакти да изтриват необратимо изпратените съобщения. (24 часа)</string> <string name="allow_your_contacts_to_send_disappearing_messages">Позволи на вашите контакти да изпращат изчезващи съобщения.</string> <string name="chat_preferences_always">винаги</string> <string name="audio_video_calls">Аудио/видео разговори</string> @@ -198,7 +195,7 @@ <string name="color_background">Фон</string> <string name="allow_message_reactions">Позволи реакции на съобщения.</string> <string name="allow_direct_messages">Позволи изпращането на лични съобщения до членовете.</string> - <string name="allow_to_delete_messages">Позволи необратимо изтриване на изпратените съобщения.</string> + <string name="allow_to_delete_messages">Позволи необратимо изтриване на изпратените съобщения. (24 часа)</string> <string name="allow_to_send_files">Позволи изпращане на файлове и медия.</string> <string name="allow_to_send_voice">Позволи изпращане на гласови съобщения.</string> <string name="allow_your_contacts_adding_message_reactions">Позволи на вашите контакти да добавят реакции към съобщения.</string> @@ -377,9 +374,9 @@ <string name="delete_after">Изтрий след</string> <string name="ttl_d">%dд</string> <string name="v5_1_custom_themes">Персонализирани теми</string> - <string name="connect_via_contact_link">Свързване чрез линк на контакта\?</string> - <string name="connect_via_group_link">Свързване чрез групов линк\?</string> - <string name="connect_via_invitation_link">Свързване чрез линк за покана\?</string> + <string name="connect_via_contact_link">Свързване чрез адрес на контакт?</string> + <string name="connect_via_group_link">Влез в групата?</string> + <string name="connect_via_invitation_link">Свързване чрез еднократен линк за връзка?</string> <string name="decryption_error">Грешка при декриптиране</string> <string name="deleted_description">изтрит</string> <string name="contact_already_exists">Контактът вече съществува</string> @@ -404,7 +401,6 @@ <string name="delete_contact_menu_action">Изтрий</string> <string name="delete_group_menu_action">Изтрий</string> <string name="connect_via_link">Свърване чрез линк</string> - <string name="create_one_time_link">Създай линк за еднократна покана</string> <string name="database_passphrase_and_export">Парола за базата данни и експортиране</string> <string name="contribute">Допринеси</string> <string name="continue_to_next_step">Продължи</string> @@ -420,7 +416,7 @@ <string name="create_profile_button">Създай</string> <string name="create_profile">Създай профил</string> <string name="delete_image">Изтрий изображение</string> - <string name="create_your_profile">Създай своя профил</string> + <string name="create_your_profile">Създай профил</string> <string name="decentralized">Децентрализиран</string> <string name="status_contact_has_e2e_encryption">контактът има e2e криптиране</string> <string name="status_contact_has_no_e2e_encryption">контактът няма e2e криптиране</string> @@ -439,8 +435,8 @@ <string name="custom_time_unit_days">дни</string> <string name="choose_file_title">Избери файл</string> <string name="if_you_received_simplex_invitation_link_you_can_open_in_browser">Ако сте получили линк за покана за SimpleX Chat, можете да го отворите във вашия браузър:</string> - <string name="desktop_scan_QR_code_from_app_via_scan_QR_code"><![CDATA[💻 настолен компютър: сканирайте показания QR код от приложението чрез <b>Сканирай QR код</b>.]]></string> - <string name="delete_pending_connection__question">Изтрий предстоящата връзка\?</string> + <string name="desktop_scan_QR_code_from_app_via_scan_QR_code"><![CDATA[💻 настолно устройство: сканирай показания QR код от приложението чрез <b>Сканирай QR код</b>.]]></string> + <string name="delete_pending_connection__question">Изтрий линк за предстоящата връзка?</string> <string name="icon_descr_email">Електронна поща</string> <string name="share_invitation_link">Сподели еднократен линк</string> <string name="one_time_link">Линк за еднократна покана</string> @@ -449,7 +445,7 @@ <string name="smp_servers_enter_manually">Въведи сървъра ръчно</string> <string name="smp_servers_delete_server">Изтрий сървър</string> <string name="dont_create_address">Не създавай адрес</string> - <string name="display_name__field">Показвано име:</string> + <string name="display_name__field">Име на профила:</string> <string name="only_client_devices_store_contacts_groups_e2e_encrypted_messages"><![CDATA[Само потребителските устройства съхраняват потребителски профили, контакти, групи и съобщения, изпратени с <b>двуслойно криптиране от край до край</b>.]]></string> <string name="receipts_contacts_title_disable">Деактивирай потвърждениeто\?</string> <string name="receipts_contacts_enable_keep_overrides">Активиране (запазване на промените)</string> @@ -478,8 +474,8 @@ <string name="delivery_receipts_are_disabled">Потвърждениeто за доставка е деактивирано!</string> <string name="scan_qr_to_connect_to_contact">За да се свърже, вашият контакт може да сканира QR код или да използва линка в приложението.</string> <string name="direct_messages">Лични съобщения</string> - <string name="display_name">Показвано Име</string> - <string name="display_name_cannot_contain_whitespace">Показваното име не може да съдържа интервал.</string> + <string name="display_name">Въведи своето име:</string> + <string name="display_name_cannot_contain_whitespace">Името не може да съдържа интервал.</string> <string name="sending_delivery_receipts_will_be_enabled">Изпращането на потвърждениe за доставка ще бъде активирано за всички контакти.</string> <string name="receipts_contacts_enable_for_all">Активиране за всички</string> <string name="error_enabling_delivery_receipts">Грешка при активирането на потвърждениeто за доставка!</string> @@ -524,7 +520,7 @@ <string name="member_role_will_be_changed_with_invitation">Ролята ще бъде променена на \"%s\". Членът ще получи нова покана.</string> <string name="conn_level_desc_direct">директна</string> <string name="renegotiate_encryption">Предоговори криптирането</string> - <string name="group_display_name_field">Групово показвано име:</string> + <string name="group_display_name_field">Въведи име на групата:</string> <string name="delete_profile">Изтрий профил</string> <string name="dont_show_again">Не показвай отново</string> <string name="ttl_h">%dч</string> @@ -546,12 +542,12 @@ <string name="enable_receipts_all">Активирай</string> <string name="simplex_link_mode_description">Описание</string> <string name="simplex_link_invitation">Еднократна покана за SimpleX</string> - <string name="display_name_invited_to_connect">поканен да се свърже</string> + <string name="display_name_invited_to_connect">покана за свързване</string> <string name="smp_server_test_delete_queue">Изтрий опашка</string> <string name="smp_server_test_disconnect">Прекъсни връзката</string> <string name="smp_server_test_download_file">Свали файл</string> - <string name="failed_to_create_user_duplicate_title">Дублирано показвано име!</string> - <string name="failed_to_create_user_duplicate_desc">Вече имате чат профил със същото показвано име. Моля, изберете друго име.</string> + <string name="failed_to_create_user_duplicate_title">Дублирано име!</string> + <string name="failed_to_create_user_duplicate_desc">Вече имате чат профил със същото име. Моля, изберете друго име.</string> <string name="la_minutes">%d минути</string> <string name="la_seconds">%d секунди</string> <string name="edit_verb">Редактирай</string> @@ -570,7 +566,7 @@ <string name="integrity_msg_duplicate">дублирано съобщение</string> <string name="privacy_and_security">Поверителност и сигурност</string> <string name="alert_text_fragment_encryption_out_of_sync_old_database">Това може да се случи, когато вие или вашата връзка използвате старо резервно копие на базата данни.</string> - <string name="self_destruct_new_display_name">Ново показвано име:</string> + <string name="self_destruct_new_display_name">Ново име:</string> <string name="enable_lock">Активирай заключване</string> <string name="enable_self_destruct">Активирай самоунищожение</string> <string name="chat_item_ttl_none">никога</string> @@ -657,7 +653,7 @@ <string name="email_invite_body">Здравей, \nСвържи се с мен през SimpleX Chat: %s</string> <string name="group_members_can_add_message_reactions">Членовете на групата могат да добавят реакции към съобщенията.</string> - <string name="group_members_can_delete">Членовете на групата могат необратимо да изтриват изпратените съобщения.</string> + <string name="group_members_can_delete">Членовете на групата могат необратимо да изтриват изпратените съобщения. (24 часа)</string> <string name="group_members_can_send_voice">Членовете на групата могат да изпращат гласови съобщения.</string> <string name="v5_2_disappear_one_message_descr">Дори когато е деактивиран в разговора.</string> <string name="v5_0_large_files_support_descr">Бързо и без чакане, докато подателят е онлайн!</string> @@ -787,14 +783,14 @@ <string name="custom_time_unit_seconds">секунди</string> <string name="custom_time_unit_weeks">седмици</string> <string name="v5_1_japanese_portuguese_interface">Японски и португалски потребителски интерфейс</string> - <string name="mobile_tap_open_in_mobile_app_then_tap_connect_in_app"><![CDATA[📱 мобилно: докоснете <b>Отваряне в мобилно приложение</b>, след което докоснете <b>Свързване</b> в приложението.]]></string> + <string name="mobile_tap_open_in_mobile_app_then_tap_connect_in_app"><![CDATA[📱 мобилно устройство: докоснете <b>Отваряне в мобилно приложение</b>, след което докоснете <b>Свързване</b> в приложението.]]></string> <string name="reject_contact_button">Отхвърляне</string> <string name="mark_unread">Маркирай като непрочетено</string> <string name="mark_read">Маркирай като прочетено</string> <string name="mute_chat">Без звук</string> <string name="image_descr_qr_code">QR код</string> <string name="icon_descr_more_button">Повече</string> - <string name="read_more_in_user_guide_with_link"><![CDATA[Прочетете повече в <font color=#0088ff>Ръководство за потребителя</font>.]]></string> + <string name="read_more_in_user_guide_with_link"><![CDATA[Прочетете повече в <font color="#0088ff">Ръководство за потребителя</font>.]]></string> <string name="mark_code_verified">Маркирай като проверено</string> <string name="is_not_verified">%s не е потвърдено</string> <string name="is_verified">%s е потвърдено</string> @@ -814,7 +810,7 @@ <string name="network_use_onion_hosts_no_desc">Няма се използват Onion хостове.</string> <string name="email_invite_subject">Нека да поговорим в SimpleX Chat</string> <string name="password_to_show">Парола за показване</string> - <string name="read_more_in_github_with_link"><![CDATA[Прочетете повече в нашето <font color=#0088ff>GitHub хранилище</font>.]]></string> + <string name="read_more_in_github_with_link"><![CDATA[Прочетете повече в нашето <font color="#0088ff">GitHub хранилище</font>.]]></string> <string name="onboarding_notifications_mode_off">Когато приложението работи</string> <string name="onboarding_notifications_mode_periodic">Периодично</string> <string name="paste_the_link_you_received">Постави получения линк</string> @@ -947,7 +943,7 @@ <string name="v4_6_reduced_battery_usage_descr">Очаквайте скоро още подобрения!</string> <string name="v5_0_polish_interface">Полски интерфейс</string> <string name="v5_1_message_reactions">Реакции на съобщения</string> - <string name="you_will_join_group">Ще се присъедините към групата, към която този линк препраща, и ще се свържете с нейните членове.</string> + <string name="you_will_join_group">Ще се свържете с всички членове на групата.</string> <string name="thousand_abbreviation">х</string> <string name="opening_database">Отваряне на база данни…</string> <string name="live">НА ЖИВО</string> @@ -1010,9 +1006,9 @@ <string name="only_your_contact_can_add_message_reactions">Само вашият контакт може да добавя реакции на съобщенията.</string> <string name="message_reactions_prohibited_in_this_chat">Реакциите на съобщения са забранени в този чат.</string> <string name="only_you_can_add_message_reactions">Само вие можете да добавяте реакции на съобщенията.</string> - <string name="only_you_can_delete_messages">Само вие можете необратимо да изтриете съобщения (вашият контакт може да ги маркира за изтриване).</string> + <string name="only_you_can_delete_messages">Само вие можете необратимо да изтриете съобщения (вашият контакт може да ги маркира за изтриване). (24 часа)</string> <string name="only_you_can_send_voice">Само вие можете да изпращате гласови съобщения.</string> - <string name="only_your_contact_can_delete">Само вашият контакт може необратимо да изтрие съобщения (можете да ги маркирате за изтриване).</string> + <string name="only_your_contact_can_delete">Само вашият контакт може необратимо да изтрие съобщения (можете да ги маркирате за изтриване). (24 часа)</string> <string name="only_your_contact_can_send_voice">Само вашият контакт може да изпраща гласови съобщения.</string> <string name="prohibit_message_reactions">Забрани реакциите на съобщенията.</string> <string name="prohibit_sending_voice_messages">Забрани изпращането на гласови съобщения.</string> @@ -1168,8 +1164,6 @@ <string name="profile_is_only_shared_with_your_contacts">Профилът се споделя само с вашите контакти.</string> <string name="delete_files_and_media_desc">Това действие не може да бъде отменено - всички получени и изпратени файлове и медия ще бъдат изтрити. Снимките с ниска разделителна способност ще бъдат запазени.</string> <string name="tap_to_activate_profile">Докосни за активиране на профил.</string> - <string name="should_be_at_least_one_profile">Трябва да има поне един потребителски профил.</string> - <string name="should_be_at_least_one_visible_profile">Трябва да има поне един видим потребителски профил.</string> <string name="language_system">Системен</string> <string name="color_title">Заглавие</string> <string name="to_share_with_your_contact">(за споделяне с вашия контакт)</string> @@ -1191,7 +1185,7 @@ <string name="delete_chat_profile_action_cannot_be_undone_warning">Това действие не може да бъде отменено - вашият профил, контакти, съобщения и файлове ще бъдат безвъзвратно загубени.</string> <string name="enable_automatic_deletion_message">Това действие не може да бъде отменено - съобщенията, изпратени и получени по-рано от избраното, ще бъдат изтрити. Може да отнеме няколко минути.</string> <string name="database_backup_can_be_restored">Опитът за промяна на паролата на базата данни не беше завършен.</string> - <string name="group_is_decentralized">Групата е напълно децентрализирана – видима е само за членовете.</string> + <string name="group_is_decentralized">Напълно децентрализирана – видима е само за членовете.</string> <string name="v4_5_transport_isolation">Транспортна изолация</string> <string name="v5_0_polish_interface_descr">Благодарение на потребителите – допринесете през Weblate!</string> <string name="alert_text_msg_bad_hash">Хешът на предишното съобщение е различен.</string> @@ -1328,7 +1322,7 @@ <string name="auth_you_will_be_required_to_authenticate_when_you_start_or_resume">Ще трябва да се идентифицирате, когато стартирате или възобновите приложението след 30 секунди във фонов режим.</string> <string name="you_are_observer">вие сте наблюдател</string> <string name="gallery_video_button">Видео</string> - <string name="you_can_connect_to_simplex_chat_founder"><![CDATA[Можете да <font color=#0088ff>се свържете с разработчиците на SimpleX Chat, за да задавате въпроси и да получавате актуализации</font>;.]]></string> + <string name="you_can_connect_to_simplex_chat_founder"><![CDATA[Можете да <font color="#0088ff">се свържете с разработчиците на SimpleX Chat, за да задавате въпроси и да получавате актуализации</font>;.]]></string> <string name="contact_wants_to_connect_with_you">иска да се свърже с вас!</string> <string name="you_can_also_connect_by_clicking_the_link"><![CDATA[Можете също да се свържете, като натиснете върху линка. Ако се отвори в браузъра, натиснете върху бутона <b>Отваряне в мобилно приложение</b>.]]></string> <string name="xftp_servers">XFTP сървъри</string> @@ -1401,4 +1395,201 @@ <string name="compose_send_direct_message_to_connect">Изпрати лично съобщение за свързване</string> <string name="member_contact_send_direct_message">изпрати лично съобщение</string> <string name="rcv_group_event_member_created_contact">свързан директно</string> + <string name="expand_verb">Разшири</string> + <string name="v5_4_block_group_members">Блокиране на членове на групата</string> + <string name="connect_plan_repeat_connection_request">Изпрати отново заявката за свързване?</string> + <string name="encryption_renegotiation_error">Грешка при повторно договаряне на криптиране</string> + <string name="rcv_direct_event_contact_deleted">изтрит контакт</string> + <string name="connect_plan_you_are_already_connecting_to_vName"><![CDATA[Вече се свързвате с <b>%1$s</b>.]]></string> + <string name="error_alert_title">Грешка</string> + <string name="v5_4_incognito_groups_descr">Създай група с автоматично генериран профилл.</string> + <string name="connect_plan_you_are_already_joining_the_group_via_this_link">Вие вече се присъединявате към групата чрез този линк.</string> + <string name="create_group_button">Създай група</string> + <string name="refresh_qr_code">Опресняване</string> + <string name="create_another_profile_button">Създай профил</string> + <string name="connected_desktop">Свързано настолно устройство</string> + <string name="group_members_2">%s и %s</string> + <string name="new_mobile_device">Ново мобилно устройство</string> + <string name="multicast_connect_automatically">Автоматично свъзрване</string> + <string name="desktop_address">Адрес на настолно устройство</string> + <string name="only_one_device_can_work_at_the_same_time">Само едно устройство може да работи едновременно</string> + <string name="connect_plan_join_your_group">Влез в твоята група?</string> + <string name="connect_plan_you_are_already_joining_the_group_vName"><![CDATA[Вече се присъединявате към групата <b>%1$s</b>.]]></string> + <string name="v5_4_link_mobile_desktop">Свържете мобилни и настолни приложения! 🔗</string> + <string name="connect_plan_this_is_your_own_one_time_link">Това е вашят еднократен линк за връзка!</string> + <string name="marked_deleted_items_description">%d съобщения са маркирани като изтрити</string> + <string name="connect_plan_group_already_exists">Групата вече съществува!</string> + <string name="v5_4_link_mobile_desktop_descr">Чрез сигурен квантово устойчив протокол.</string> + <string name="open_on_mobile_and_scan_qr_code"><![CDATA[Отвори <i>Използвай от настолно устройство</i> в мобилното приложение и сканирай QR кода.]]></string> + <string name="connect_plan_already_connecting">В процес на свързване!</string> + <string name="v5_4_block_group_members_descr">Скриване на нежелани съобщения.</string> + <string name="desktop_incompatible_version">Несъвместима версия</string> + <string name="new_desktop"><![CDATA[<i>(ново)</i>]]></string> + <string name="unlink_desktop_question">Забрави настолно устройство?</string> + <string name="v5_4_better_groups">По-добри групи</string> + <string name="linked_desktop_options">Настройки на запомнени настолни устройства</string> + <string name="video_decoding_exception_desc">Видеото не може да бъде декодирано. Моля, опитайте с друг видеоклип или се свържете с разработчиците.</string> + <string name="rcv_group_event_1_member_connected">%s свързан</string> + <string name="random_port">Случаен</string> + <string name="linked_desktops">Запомнени настолни устройства</string> + <string name="discover_on_network">Открий през локалната мрежа</string> + <string name="rcv_group_and_other_events">и %d други събития</string> + <string name="connect_plan_connect_via_link">Свърване чрез линк?</string> + <string name="v5_4_incognito_groups">Инкогнито групи</string> + <string name="connect_plan_already_joining_the_group">Вече се присъединихте към групата!</string> + <string name="group_members_n">%s, %s и %d членове</string> + <string name="this_device">Това устройство</string> + <string name="moderated_items_description">%1$d съобщения, модерирани от %2$s</string> + <string name="unblock_member_button">Отблокирай член</string> + <string name="remote_host_was_disconnected_toast"><![CDATA[Връзкарта с <b>%s</b> мобилно устройство бе прекъсната]]></string> + <string name="waiting_for_desktop">Изчакване на настолно устройство…</string> + <string name="v5_4_better_groups_descr">По-бързо присъединяване и по-надеждни съобщения.</string> + <string name="connect_plan_connect_to_yourself">Свърване със себе си?</string> + <string name="linked_mobiles">Запомнени мобилни устройства</string> + <string name="desktop_device">Настолно устройство</string> + <string name="connected_to_desktop">Свързан с настолно устройство</string> + <string name="contact_tap_to_connect">Докосни за свързване</string> + <string name="this_device_name">Името на това устройство</string> + <string name="connect_plan_you_are_already_in_group_vName"><![CDATA[Вече сте в група <b>%1$s</b>.]]></string> + <string name="connect_plan_this_is_your_own_simplex_address">Това е вашият личен SimpleX адрес!</string> + <string name="loading_remote_file_title">Зареждане на файла</string> + <string name="connecting_to_desktop">Свързване с настолно устройство</string> + <string name="found_desktop">Намерено настолно устройство</string> + <string name="alert_text_encryption_renegotiation_failed">Неуспешно повторно договаряне на криптирането.</string> + <string name="desktop_devices">Настолни устройства</string> + <string name="correct_name_to">Поправи име на %s?</string> + <string name="not_compatible">Несъвместим!</string> + <string name="waiting_for_mobile_to_connect">Изчаква се мобилното устройство да се свърже:</string> + <string name="delete_messages__question">Изтрий %d съобщения?</string> + <string name="link_a_mobile">Свържи мобилно устройство</string> + <string name="connect_with_contact_name_question">Свързване с %1$s?</string> + <string name="remove_member_button">Премахни член</string> + <string name="block_member_confirmation">Блокирай</string> + <string name="unblock_member_question">Отблокирай член?</string> + <string name="blocked_items_description">%d блокирани съобщения</string> + <string name="open_port_in_firewall_desc">За да позволите на мобилно приложение да се свърже с настолното, отворете този порт във вашата защитна стена, ако тя е активирана</string> + <string name="block_member_button">Блокирай член</string> + <string name="settings_section_title_use_from_desktop">Използвай от настолно устройство</string> + <string name="connected_mobile">Свързано мобилно устройство</string> + <string name="session_code">Код на сесията</string> + <string name="connect_plan_repeat_join_request">Изпрати отново заявката за присъединяване?</string> + <string name="create_chat_profile">Създай чат профил</string> + <string name="button_remove_member_question">Премахни член?</string> + <string name="app_was_crashed">Покажи грешките</string> + <string name="delete_and_notify_contact">Изтрий и уведоми контакт</string> + <string name="connect_plan_you_are_already_connecting_via_this_one_time_link">Вече се свързвате чрез този еднократен линк за връзка!</string> + <string name="connect_plan_open_group">Отвори група</string> + <string name="desktop_connection_terminated">Връзката е прекратена</string> + <string name="this_device_version"><![CDATA[<i>(това устройство v%s)</i>]]></string> + <string name="unlink_desktop">Забрави</string> + <string name="unblock_member_desc">Съобщенията от %s ще бъдат показани!</string> + <string name="this_device_name_shared_with_mobile">Името на устройството ще бъде споделено със свързания мобилен клиент.</string> + <string name="error_sending_message_contact_invitation">Грешка при изпращане на покана</string> + <string name="verify_code_on_mobile">Потвръди кода на мобилното устройство</string> + <string name="open_port_in_firewall_title">Отвори порт в защитната стена</string> + <string name="enter_this_device_name">Въведи името на това устройство…</string> + <string name="error">Грешка</string> + <string name="connect_to_desktop">Свързване с настолно устройство</string> + <string name="non_content_uri_alert_text">Споделихте невалиден файлов път. Докладвайте проблема на разработчиците на приложението.</string> + <string name="disconnect_remote_hosts">Прекъсни връзката с мобилните устройства?</string> + <string name="disconnect_remote_host">Прекъсни връзката</string> + <string name="block_member_question">Блокирай члена?</string> + <string name="rcv_group_events_count">%d групови събития</string> + <string name="invalid_name">Невалидно име!</string> + <string name="group_member_role_author">автор</string> + <string name="connected_to_mobile">Свързан с мобилно устройство</string> + <string name="bad_desktop_address">Грешен адрес на настолното устройство</string> + <string name="paste_desktop_address">Постави адрес на настолно устройство</string> + <string name="connect_plan_this_is_your_link_for_group_vName"><![CDATA[Това е вашят линк за група <b>%1$s</b>!]]></string> + <string name="verify_code_with_desktop">Потвръди кода с настолното устройство</string> + <string name="scan_qr_code_from_desktop">Сканирай QR код от настолното устройство</string> + <string name="unblock_member_confirmation">Отблокирай</string> + <string name="devices">Устройства</string> + <string name="multicast_discoverable_via_local_network">Откриваем през локалната мрежа</string> + <string name="v5_4_more_things_descr">- по желание уведомете изтритите контакти. +\n- имена на профили с интервали. +\n- и още!</string> + <string name="non_content_uri_alert_title">Невалиден файлов път</string> + <string name="connect_plan_you_have_already_requested_connection_via_this_address">Вече сте заявили връзка през този адрес!</string> + <string name="terminal_always_visible">Покажи конзолата в нов прозорец</string> + <string name="scan_from_mobile">Сканиране от мобилно устройство</string> + <string name="verify_connections">Потвръди връзките</string> + <string name="disconnect_desktop_question">Прекъсни връзката с настолното устройство?</string> + <string name="loading_remote_file_desc">Моля, изчакайте, докато файлът се зареди от свързаното мобилно устройство</string> + <string name="block_member_desc">Всички нови съобщения от %s ще бъдат скрити!</string> + <string name="desktop_app_version_is_incompatible">Версията на настолното приложение %s не е съвместима с това приложение.</string> + <string name="verify_connection">Потвръди връзките</string> + <string name="no_connected_mobile">Няма свързано мобилно устройство</string> + <string name="blocked_item_description">блокиран</string> + <string name="you_can_make_address_visible_via_settings">Можете да го направите видим за вашите контакти в SimpleX чрез Настройки.</string> + <string name="recent_history_is_not_sent_to_new_members">Историята не се изпраща на нови членове.</string> + <string name="retry_verb">Опитай отново</string> + <string name="camera_not_available">Камерата е неодстъпна</string> + <string name="enable_sending_recent_history">Изпращане до последните 100 съобщения на нови членове.</string> + <string name="add_contact_button_to_create_link_or_connect_via_link"><![CDATA[<b>Добави контакт</b>: за създаване на нов линк или свързване чрез получен линк за връзка.]]></string> + <string name="disable_sending_recent_history">Не изпращай история на нови членове.</string> + <string name="error_showing_content">грешка при показване на съдържанието</string> + <string name="or_show_this_qr_code">Или покажи този код</string> + <string name="recent_history_is_sent_to_new_members">На новите членове се изпращат до последните 100 съобщения.</string> + <string name="code_you_scanned_is_not_simplex_link_qr_code">QR кодът, който сканирахте, не е SimpleX линк за връзка.</string> + <string name="the_text_you_pasted_is_not_a_link">Текстът, който поставихте, не е SimpleX линк за връзка.</string> + <string name="error_showing_message">грешка при показване на съобщението</string> + <string name="enable_camera_access">Разреши достъпа до камерата</string> + <string name="you_can_view_invitation_link_again">Можете да видите отново линкът за покана в подробностите за връзката.</string> + <string name="keep_unused_invitation_question">Запази неизползваната покана за връзка?</string> + <string name="share_this_1_time_link">Сподели този еднократен линк за връзка</string> + <string name="create_group_button_to_create_new_group"><![CDATA[<b>Създай група</b>: за създаване на нова група.]]></string> + <string name="recent_history">Видима история</string> + <string name="la_app_passcode">Код за достъп до приложението</string> + <string name="new_chat">Нов чат</string> + <string name="loading_chats">Чатовете се зареждат…</string> + <string name="creating_link">Линкът се създава…</string> + <string name="or_scan_qr_code">Или сканирай QR код</string> + <string name="invalid_qr_code">Невалиден QR код</string> + <string name="add_contact_tab">Добави контакт</string> + <string name="tap_to_scan">Докосни за сканиране</string> + <string name="keep_invitation_link">Запази</string> + <string name="tap_to_paste_link">Докосни за поставяне на линк за връзка</string> + <string name="search_or_paste_simplex_link">Търсене или поставяне на SimpleX линк</string> + <string name="start_chat_question">Стартирай чата?</string> + <string name="chat_is_stopped_you_should_transfer_database">Чатът е спрян. Ако вече сте използвали тази база данни на друго устройство, трябва да я прехвърлите обратно, преди да стартирате чата отново.</string> + <string name="remote_ctrl_error_bad_invitation">Настолното устройство има грешен код за връзка</string> + <string name="remote_ctrl_error_bad_version">Настолното устройство е с неподдържана версия. Моля, уверете се, че използвате една и съща версия и на двете устройства</string> + <string name="possible_deadlock_desc">Изпълнението на кода отнема твърде много време: %1$d секунди. Вероятно приложението е замразено: %2$s</string> + <string name="possible_slow_function_title">Бавна функция</string> + <string name="possible_slow_function_desc">Изпълнението на функцията отнема твърде много време: %1$d секунди: %2$s</string> + <string name="show_internal_errors">Покажи вътрешните грешки</string> + <string name="remote_host_disconnected_from"><![CDATA[Прекъсната е връзката с мобилното устройство <b>%s</b> с причина: %s]]></string> + <string name="remote_ctrl_was_disconnected_title">Връзката е прекъсната</string> + <string name="failed_to_create_user_invalid_title">Невалидно име!</string> + <string name="failed_to_create_user_invalid_desc">Това име е невалидно. Моля, изберете друго име.</string> + <string name="remote_host_was_disconnected_title">Връзката е прекъсната</string> + <string name="remote_ctrl_disconnected_with_reason">Прекъсната е връзката с причината: %s</string> + <string name="remote_host_error_missing"><![CDATA[Мобилното устройство <b>%s</b> липсва]]></string> + <string name="remote_host_error_inactive"><![CDATA[Мобилното устройство <b>%s</b> е неактивно]]></string> + <string name="remote_host_error_busy"><![CDATA[Мобилното устройство <b>%s</b> е заето]]></string> + <string name="remote_host_error_timeout"><![CDATA[Времето за изчакване е достигнато при свързване с мобилното устройство <b>%s</b>]]></string> + <string name="remote_host_error_bad_state"><![CDATA[Връзката с мобилното устройство <b>%s</b> е в лошо състояние]]></string> + <string name="remote_host_error_bad_version"><![CDATA[Мобилното устройство <b>%s</b> е с неподдържана версия. Моля, уверете се, че използвате една и съща версия и на двете устройства]]></string> + <string name="remote_host_error_disconnected"><![CDATA[Връзката с мобилното устройство <b>%s</b> бе прекъсната]]></string> + <string name="remote_ctrl_error_inactive">Настолното устройство е неактивно</string> + <string name="remote_ctrl_error_timeout">Времето за изчакване е достигнато при свързване с настолното устройство</string> + <string name="remote_ctrl_error_bad_state">Връзката с настолното устройство е в лошо състояние</string> + <string name="remote_ctrl_error_busy">Настолното устройство е заето</string> + <string name="remote_ctrl_error_disconnected">Връзката с настолното устройство бе прекъсната</string> + <string name="agent_critical_error_title">Критична грешка</string> + <string name="past_member_vName">Бивш член %1$s</string> + <string name="group_member_status_unknown">неизвестен статус</string> + <string name="group_member_status_unknown_short">неизвестен</string> + <string name="agent_internal_error_title">Вътрешна грешка</string> + <string name="agent_internal_error_desc">Моля, докладвайте го на разработчиците: +\n%s</string> + <string name="restart_chat_button">Рестартирай чата</string> + <string name="agent_critical_error_desc">Моля, докладвайте го на разработчиците: +\n%s +\n +\nПрепоръчително е да рестартирате приложението.</string> + <string name="developer_options_section">Опции за разработчици</string> + <string name="show_slow_api_calls">Показване на бавни API заявки</string> + <string name="possible_deadlock_title">Грешка в заключено положение</string> </resources> \ No newline at end of file diff --git a/apps/multiplatform/common/src/commonMain/resources/MR/cs/strings.xml b/apps/multiplatform/common/src/commonMain/resources/MR/cs/strings.xml index 75d09ecfb2..1134129845 100644 --- a/apps/multiplatform/common/src/commonMain/resources/MR/cs/strings.xml +++ b/apps/multiplatform/common/src/commonMain/resources/MR/cs/strings.xml @@ -11,7 +11,7 @@ <string name="smp_servers_add">Přidat server…</string> <string name="network_enable_socks_info">Přistupovat k serverům přes SOCKS proxy na portu %d\? Před povolením této možnosti musí být spuštěna proxy.</string> <string name="accept_feature">Přijmout</string> - <string name="allow_your_contacts_to_send_disappearing_messages">Povolte svým kontaktům odesílat mizící zprávy.</string> + <string name="allow_your_contacts_to_send_disappearing_messages">Povolit svým kontaktům odesílat mizící zprávy.</string> <string name="about_simplex_chat">O SimpleX Chat</string> <string name="smp_servers_add_to_another_device">Přidat do jiného zařízení</string> <string name="allow_verb">Povolit</string> @@ -31,11 +31,11 @@ <string name="accept_contact_incognito_button">Přijmout inkognito</string> <string name="accept_connection_request__question">Přijmout žádost o připojení\?</string> <string name="all_group_members_will_remain_connected">Všichni členové skupiny zůstanou připojeni.</string> - <string name="allow_irreversible_message_deletion_only_if">Povolte nevratné smazání zprávy pouze v případě, že vám to váš kontakt dovolí.</string> + <string name="allow_irreversible_message_deletion_only_if">Povolte nevratné smazání zprávy pouze v případě, že vám to váš kontakt povolí. (24 hodin)</string> <string name="allow_direct_messages">Přímé zprávy členům povoleny.</string> - <string name="allow_to_delete_messages">Nevratné mazání odeslaných zpráv povoleno.</string> + <string name="allow_to_delete_messages">Povolit nevratné mazání odeslaných zpráv. (24 hodin)</string> <string name="clear_chat_warning">Všechny zprávy budou smazány – tuto akci nelze vrátit zpět! Zprávy budou smazány POUZE pro vás.</string> - <string name="allow_your_contacts_irreversibly_delete">Umožněte svým kontaktům nevratně odstranit odeslané zprávy.</string> + <string name="allow_your_contacts_irreversibly_delete">Povolit svým kontaktům nevratně odstranit odeslané zprávy. (24 hodin)</string> <string name="allow_your_contacts_to_send_voice_messages">Povolte svým kontaktům odesílání hlasových zpráv.</string> <string name="button_create_group_link">Vytvořit odkaz</string> <string name="delete_link_question">Smazat odkaz\?</string> @@ -45,9 +45,9 @@ <string name="info_row_connection">Připoj</string> <string name="conn_level_desc_indirect">nepřímé (%1$s)</string> <string name="conn_stats_section_title_servers">SERVERY</string> - <string name="receiving_via">Příjímáno přez</string> + <string name="receiving_via">Příjímáno přes</string> <string name="create_secret_group_title">Vytvoření tajné skupiny</string> - <string name="group_display_name_field">Zobrazený název skupiny:</string> + <string name="group_display_name_field">Zadejte název skupiny:</string> <string name="group_full_name_field">Úplný název skupiny:</string> <string name="group_main_profile_sent">Váš chat profil bude zaslán členům skupiny</string> <string name="group_profile_is_stored_on_members_devices">Profil skupiny je uložen v zařízeních členů, nikoli na serverech.</string> @@ -65,7 +65,7 @@ <string name="chat_preferences_always">vždy</string> <string name="set_group_preferences">Nastavení skupinových předvoleb</string> <string name="your_preferences">Vaše preference</string> - <string name="timed_messages">Mizící zprávy</string> + <string name="timed_messages">Mizející zprávy</string> <string name="feature_enabled_for_contact">povoleno pro kontakt</string> <string name="feature_received_prohibited">přijaté, zakázané</string> <string name="both_you_and_your_contact_can_send_disappearing">Vy i váš kontakt můžete posílat mizící zprávy.</string> @@ -85,9 +85,9 @@ <string name="v4_4_verify_connection_security_desc">Porovnejte bezpečnostní kódy se svými kontakty.</string> <string name="app_name">SimpleX</string> <string name="thousand_abbreviation">k</string> - <string name="connect_via_contact_link">Připojit se odkazem\?</string> - <string name="connect_via_invitation_link">Připojit se pozvánkou\?</string> - <string name="connect_via_group_link">Připojit se odkazem skupiny\?</string> + <string name="connect_via_contact_link">Připojit přez adresu kontaktu?</string> + <string name="connect_via_invitation_link">Připojit přez jednorázovou pozvánku?</string> + <string name="connect_via_group_link">Připojit se do skupiny?</string> <string name="profile_will_be_sent_to_contact_sending_link">Váš profil bude odeslán kontaktu, od kterého jste obdrželi tento odkaz.</string> <string name="server_connected">připojeno</string> <string name="server_error">chyba</string> @@ -191,8 +191,6 @@ <string name="to_start_a_new_chat_help_header">Pro zahájení nové konverzace</string> <string name="chat_help_tap_button">Klepněte na tlačítko</string> <string name="above_then_preposition_continuation">potom:</string> - <string name="add_new_contact_to_create_one_time_QR_code"><![CDATA[<b>Přidejte nový kontakt</b>: vytvořte jednorázý QR kód pro váš kontakt.]]></string> - <string name="scan_QR_code_to_connect_to_contact_who_shows_QR_code"><![CDATA[<b>Naskenujte QR kód</b>: připojíte se ke kontaktu, který vám QR kód ukázal.]]></string> <string name="desktop_scan_QR_code_from_app_via_scan_QR_code"><![CDATA[💻 počítač: naskenujte QR kód z aplikace přez <b>Skenovat QR kód</b>.]]></string> <string name="clear_chat_question">Vyčistit chat\?</string> <string name="clear_verb">Vyčistit</string> @@ -209,7 +207,6 @@ <string name="you_will_be_connected_when_group_host_device_is_online">Ke skupině budete připojeni, až bude zařízení hostitele skupiny online, vyčkejte prosím nebo se podívejte později!</string> <string name="you_will_be_connected_when_your_connection_request_is_accepted">Budete připojeni, jakmile bude vaše žádost o připojení přijata, vyčkejte prosím nebo se podívejte později!</string> <string name="connection_request_sent">Požadavek na připojení byl odeslán!</string> - <string name="create_one_time_link">Vytvořit jednorázovou pozvánku</string> <string name="one_time_link">Jednorázová pozvánka</string> <string name="security_code">Bezpečnostní kód</string> <string name="is_verified">%s je ověřeno</string> @@ -242,7 +239,7 @@ <string name="the_messaging_and_app_platform_protecting_your_privacy_and_security">Platforma pro zasílání zpráv a aplikace chránící vaše soukromí a bezpečnost.</string> <string name="create_profile">Vytvořit profil</string> <string name="profile_is_only_shared_with_your_contacts">Profil je sdílen pouze s vašimi kontakty.</string> - <string name="display_name_cannot_contain_whitespace">Zobrazované jméno nesmí obsahovat mezery.</string> + <string name="display_name_cannot_contain_whitespace">Zobrazované jméno nesmí obsahovat bílé znaky.</string> <string name="bold_text">tučně</string> <string name="callstatus_in_progress">probíhající hovor</string> <string name="decentralized">Decentralizovaná</string> @@ -268,7 +265,7 @@ <string name="settings_section_title_settings">NASTAVENÍ</string> <string name="settings_section_title_help">NÁPOVĚDA</string> <string name="settings_section_title_device">ZAŘÍZENÍ</string> - <string name="settings_section_title_chats">CHATY</string> + <string name="settings_section_title_chats">KONVERZACE</string> <string name="settings_experimental_features">Experimentální funkce</string> <string name="settings_section_title_socks">SOCKS PROXY</string> <string name="settings_section_title_icon">IKONA APLIKACE</string> @@ -278,29 +275,29 @@ <string name="export_database">Export databáze</string> <string name="import_database">Import databáze</string> <string name="delete_database">Smazat databázi</string> - <string name="error_exporting_chat_database">Chyba exportu chat databáze</string> + <string name="error_exporting_chat_database">Chyba při exportu databáze chatu</string> <string name="import_database_confirmation">Import</string> - <string name="restart_the_app_to_use_imported_chat_database">Restartujte aplikaci, abyste mohli používat importovanou chat databázi.</string> + <string name="restart_the_app_to_use_imported_chat_database">Restartujte aplikaci, abyste mohli používat importovanou databázi chatu.</string> <string name="delete_chat_profile_question">Smazat chat profil\?</string> <string name="delete_chat_profile_action_cannot_be_undone_warning">Tuto akci nelze vzít zpět! Váš profil, kontakty, zprávy a soubory budou nenávratně ztraceny.</string> <string name="restart_the_app_to_create_a_new_chat_profile">Restartujte aplikaci a vytvořte nový chat profil.</string> - <string name="you_must_use_the_most_recent_version_of_database">Nejnovější verzi chat databáze musíte používat POUZE v jednom zařízení, jinak se může stát, že přestanete přijímat zprávy od některých kontaktů.</string> + <string name="you_must_use_the_most_recent_version_of_database">Nejnovější verzi databáze chatu musíte používat POUZE v jednom zařízení, jinak se může stát, že přestanete přijímat zprávy od některých kontaktů.</string> <string name="stop_chat_to_enable_database_actions">Zastavte chat a povolte akce s databází.</string> <string name="files_and_media_section">Soubory a média</string> <string name="delete_files_and_media_question">Smazat soubory a média\?</string> <string name="delete_messages">Odstranit zprávy</string> - <string name="remove_passphrase_from_keychain">Odstranit frázi z úložiště klíčů\?</string> + <string name="remove_passphrase_from_keychain">Odstranit přístupovou frázi z úložiště klíčů?</string> <string name="notifications_will_be_hidden">Oznámení budou doručována pouze do doby, než se aplikace zastaví!</string> <string name="remove_passphrase">Odstranit</string> <string name="update_database">Aktualizovat</string> - <string name="current_passphrase">Aktuální fráze…</string> + <string name="current_passphrase">Aktuální přístupová fráze…</string> <string name="update_database_passphrase">Aktualizovat přístupovou frázi</string> <string name="enter_correct_current_passphrase">Zadejte prosím správnou aktuální přístupovou frázi.</string> - <string name="database_is_not_encrypted">Chat databáze není šifrována - nastavte přístupovou frázi pro její ochranu.</string> + <string name="database_is_not_encrypted">Databáze chatu není šifrována - nastavte přístupovou frázi pro její ochranu.</string> <string name="keychain_is_storing_securely">K bezpečnému uložení přístupové fráze slouží úložiště klíčů Android - umožňuje fungování služby oznámení.</string> <string name="impossible_to_recover_passphrase"><![CDATA[<b>Upozornění</b>: pokud přístupovou frázi ztratíte, NEBUDE možné ji obnovit ani změnit.]]></string> - <string name="database_will_be_encrypted_and_passphrase_stored">Databáze bude šifrována a přístupová fráze bude uložena v úložišti klíčů.</string> - <string name="store_passphrase_securely">Heslo uložte bezpečně, v případě jeho ztráty jej NEBUDE možné změnit.</string> + <string name="database_will_be_encrypted_and_passphrase_stored">Databáze bude zašifrována a přístupová fráze bude uložena v úložišti klíčů.</string> + <string name="store_passphrase_securely">Přístupovou frázi uložte bezpečně, v případě její ztráty ji NEBUDE možné změnit.</string> <string name="file_with_path">Soubor: %s</string> <string name="database_passphrase_is_required">Pro otevření chatu je vyžadována přístupová fráze.</string> <string name="unknown_error">Neznámá chyba</string> @@ -309,7 +306,7 @@ <string name="restore_database_alert_desc">Po obnovení zálohy databáze zadejte předchozí frázi. Tuto akci nelze vrátit zpět.</string> <string name="chat_is_stopped_indication">Chat je zastaven</string> <string name="chat_archive_header">Chat se archivuje</string> - <string name="delete_chat_archive_question">Smazat chat archiv\?</string> + <string name="delete_chat_archive_question">Smazat archiv chatu?</string> <string name="join_group_question">Připojit se ke skupině\?</string> <string name="join_group_button">Připojte se na</string> <string name="leave_group_button">Opustit</string> @@ -354,12 +351,12 @@ <string name="next_generation_of_private_messaging">Příští generace soukromé komunikace</string> <string name="people_can_connect_only_via_links_you_share">Lidé se s vámi mohou spojit pouze prostřednictvím odkazu, který sdílíte.</string> <string name="integrity_msg_bad_hash">špatný kontrolní součet zprávy</string> - <string name="chat_database_imported">Chat databáze importována</string> + <string name="chat_database_imported">Databáze chatu importována</string> <string name="new_passphrase">Nová přístupová fráze…</string> - <string name="save_passphrase_and_open_chat">Uložte frázi a otevřete chat</string> - <string name="chat_archive_section">CHAT ARCHIV</string> + <string name="save_passphrase_and_open_chat">Uložte přístupovou frázi a otevřete chat</string> + <string name="chat_archive_section">ARCHIV CHATU</string> <string name="no_contacts_selected">Nebyl vybrán žádný kontakt</string> - <string name="invite_prohibited_description">Snažíte se pozvat kontakt se kterým jste sdíleli inkognito profil, do skupiny ve které používáte svůj hlavní profil</string> + <string name="invite_prohibited_description">Snažíte se pozvat kontakt, se kterým jste sdíleli inkognito profil, do skupiny, ve které používáte svůj hlavní profil</string> <string name="info_row_group">Skupina</string> <string name="network_options_revert">Vrátit</string> <string name="updating_settings_will_reconnect_client_to_all_servers">Aktualizací nastavení se klient znovu připojí ke všem serverům.</string> @@ -381,8 +378,8 @@ <string name="to_verify_compare">Chcete-li ověřit koncové šifrování u svého kontaktu, porovnejte (nebo naskenujte) kód na svých zařízeních.</string> <string name="your_settings">Vaše nastavení</string> <string name="your_simplex_contact_address">Vaše SimpleX adresa</string> - <string name="database_passphrase_and_export">Heslo databáze a export</string> - <string name="your_chat_profiles">Chat profily</string> + <string name="database_passphrase_and_export">Přístupová fráze k databázi a export</string> + <string name="your_chat_profiles">Vaše chatovací profily</string> <string name="chat_with_the_founder">Zaslat otázky a nápady</string> <string name="smp_servers_test_server">Test serveru</string> <string name="enter_one_ICE_server_per_line">Servery ICE (jeden na řádek)</string> @@ -422,9 +419,9 @@ <string name="image_saved">Obrázek uložen do galerie</string> <string name="icon_descr_file">Soubor</string> <string name="large_file">Velký soubor!</string> - <string name="file_will_be_received_when_contact_is_online">Soubor bude přijat, až bude váš kontakt online, vyčkejte prosím, nebo se podívejte později!</string> + <string name="file_will_be_received_when_contact_is_online">Soubor bude přijat, až bude váš kontakt online, vyčkejte prosím nebo se podívejte později!</string> <string name="file_saved">Soubor uložen</string> - <string name="file_not_found">Soubor nenalezen</string> + <string name="file_not_found">Soubor nebyl nalezen</string> <string name="voice_message_with_duration">Hlasová zpráva (%1$s)</string> <string name="delete_contact_all_messages_deleted_cannot_undo_warning">Kontakt a všechny zprávy budou smazány - nelze to vzít zpět!</string> <string name="button_delete_contact">Smazat kontakt</string> @@ -461,7 +458,7 @@ <string name="protect_app_screen">Skrývat aplikaci</string> <string name="send_link_previews">Odesílat náhledy odkazů</string> <string name="full_backup">Zálohovat data aplikace</string> - <string name="confirm_new_passphrase">Potvrdit frázi…</string> + <string name="confirm_new_passphrase">Potvrdit novou přístupovou frázi…</string> <string name="error_with_info">Chyba: %s</string> <string name="leave_group_question">Opustit skupinu\?</string> <string name="icon_descr_group_inactive">Skupina je neaktivní</string> @@ -469,8 +466,8 @@ <string name="clear_contacts_selection_button">Vyčistit</string> <string name="switch_verb">Přepnout</string> <string name="member_role_will_be_changed_with_notification">Role bude změněna na \"%s\". Všichni ve skupině budou informováni.</string> - <string name="error_removing_member">Chyba odebírání člena</string> - <string name="error_saving_group_profile">Chyba ukládání profilu skupiny</string> + <string name="error_removing_member">Chyba při odebrání člena</string> + <string name="error_saving_group_profile">Chyba při ukládání profilu skupiny</string> <string name="network_option_seconds_label">vteřiny</string> <string name="incognito_info_allows">Umožňuje mít v jednom chat profilu mnoho anonymních spojení bez sdílení údajů mezi nimi.</string> <string name="incognito_info_share">Pokud s někým sdílíte inkognito profil, bude použit pro skupiny, do kterých vás pozve.</string> @@ -487,7 +484,7 @@ <string name="v4_3_irreversible_message_deletion">Nevratné mazání zpráv</string> <string name="v4_3_improved_server_configuration">Vylepšena konfigurace serveru</string> <string name="v4_3_improved_privacy_and_security">Vylepšena ochrana soukromí a zabezpečení</string> - <string name="v4_3_improved_privacy_and_security_desc">Skryta obrazovka aplikace v posledních aplikacích.</string> + <string name="v4_3_improved_privacy_and_security_desc">Skrytí obrazovky aplikace v posledních aplikacích.</string> <string name="v4_4_disappearing_messages_desc">Odeslané zprávy se po uplynutí nastavené doby odstraní.</string> <string name="v4_4_live_messages">Živé zprávy</string> <string name="v4_4_live_messages_desc">Příjemci uvidí aktualizaci během psaní.</string> @@ -496,17 +493,17 @@ <string name="v4_4_french_interface_descr">Díky uživatelům - překládejte prostřednictvím Weblate!</string> <string name="v4_5_multiple_chat_profiles">Více chat profilů</string> <string name="v4_5_multiple_chat_profiles_descr">Různá jména, avataři a izolace přenosu.</string> - <string name="v4_5_message_draft">Návrh zpráv</string> + <string name="v4_5_message_draft">Návrh zprávy</string> <string name="v4_5_message_draft_descr">Zachování posledního návrhu zprávy s přílohami.</string> <string name="v4_5_transport_isolation">Izolace přenosu</string> - <string name="v4_5_transport_isolation_descr">Podle chat profilu (výchozí) nebo podle připojení (BETA).</string> - <string name="you_will_join_group">Připojíte se ke skupině, na kterou odkazuje tento odkaz, a spojíte se s jejími členy.</string> + <string name="v4_5_transport_isolation_descr">Podle profilu chatu (výchozí) nebo podle připojení (BETA).</string> + <string name="you_will_join_group">Připojtíte se ke všem členům skupiny.</string> <string name="connect_via_link_verb">Připojení</string> <string name="connected_to_server_to_receive_messages_from_contact">Jste připojeni k serveru, který se používá k přijímání zpráv od tohoto kontaktu.</string> <string name="trying_to_connect_to_server_to_receive_messages_with_error">Pokoušíte se připojit k serveru používaném pro příjem zpráv od tohoto kontaktu (chyba: %1$s).</string> - <string name="marked_deleted_description">označit jako smazáno</string> + <string name="marked_deleted_description">označeno jako smazáno</string> <string name="sending_files_not_yet_supported">Odesílání souborů zatím není podporováno</string> - <string name="receiving_files_not_yet_supported">Přijímání souborů zatím není podporováno</string> + <string name="receiving_files_not_yet_supported">přijímání souborů zatím není podporováno</string> <string name="sender_you_pronoun">ty</string> <string name="unknown_message_format">neznámý formát zprávy</string> <string name="invalid_message_format">neplatný formát zprávy</string> @@ -519,8 +516,8 @@ <string name="error_joining_group">Chyba připojování ke skupině</string> <string name="cannot_receive_file">Nelze přijmout soubor</string> <string name="sender_cancelled_file_transfer">Odesílatel zrušil přenos souboru.</string> - <string name="error_receiving_file">Chyba příjmu souboru</string> - <string name="error_creating_address">Chyba vytváření adresy</string> + <string name="error_receiving_file">Chyba při příjmu souboru</string> + <string name="error_creating_address">Chyba při vytváření adresy</string> <string name="please_check_correct_link_and_maybe_ask_for_a_new_one">Zkontrolujte, zda jste použili správný odkaz, nebo požádejte kontakt, aby vám poslal jiný.</string> <string name="connection_error_auth_desc">Pokud váš kontakt neodstranil připojení nebo tento odkaz již nebyl použit, může se jednat o chybu – nahlaste ji. \nChcete-li se připojit, požádejte svůj kontakt o vytvoření dalšího odkazu na připojení a zkontrolujte, zda máte stabilní připojení k síti.</string> @@ -619,7 +616,7 @@ <string name="markdown_help">Nápověda k markdown</string> <string name="smp_servers_save">Uložit servery</string> <string name="markdown_in_messages">Markdown ve zprávách</string> - <string name="smp_servers_test_servers">Testovat servery</string> + <string name="smp_servers_test_servers">Testovací servery</string> <string name="smp_servers_preset_server">Přednastavený server</string> <string name="smp_servers_your_server">Váš server</string> <string name="smp_servers_your_server_address">Adresa vašeho serveru</string> @@ -651,15 +648,15 @@ <string name="core_version">Verze jádra: v%s</string> <string name="delete_address__question">Smazat adresu\?</string> <string name="all_your_contacts_will_remain_connected">Všechny vaše kontakty zůstanou připojeny.</string> - <string name="display_name__field">Zobrazované jméno:</string> + <string name="display_name__field">Profilové jméno:</string> <string name="your_profile_is_stored_on_device_and_shared_only_with_contacts_simplex_cannot_see_it">Váš profil je uložen v zařízení a je sdílen pouze s vašimi kontakty. SimpleX servery váš profil vidět nemohou.</string> <string name="save_preferences_question">Uložit předvolby\?</string> <string name="save_and_notify_contact">Uložit a upozornit kontakt</string> <string name="save_and_notify_contacts">Uložit a upozornit kontakty</string> - <string name="you_control_your_chat">Kontrolujete chat!</string> + <string name="you_control_your_chat">Kontrolujete konverzaci!</string> <string name="we_do_not_store_contacts_or_messages_on_servers">Na serverech neukládáme žádné vaše kontakty ani zprávy (po doručení).</string> <string name="your_profile_is_stored_on_your_device">Váš profil, kontakty a doručené zprávy jsou uloženy ve vašem zařízení.</string> - <string name="display_name">Zobrazované jméno</string> + <string name="display_name">Zadejte vaše jméno:</string> <string name="create_profile_button">Vytvořit</string> <string name="how_to_use_markdown">Jak používat markdown</string> <string name="you_can_use_markdown_to_format_messages__prompt">K formátování zpráv můžete použít markdown:</string> @@ -721,13 +718,13 @@ <string name="settings_section_title_you">VY</string> <string name="settings_section_title_support">PODPOŘIT SIMPLEX CHAT</string> <string name="settings_developer_tools">Nástroje pro vývojáře</string> - <string name="settings_section_title_incognito">inkognito mód</string> - <string name="your_chat_database">Chat databáze</string> + <string name="settings_section_title_incognito">Inkognito mód</string> + <string name="your_chat_database">Vaše chatovací databáze</string> <string name="run_chat_section">SPUSTIT CHAT</string> <string name="chat_is_running">Chat je spuštěn</string> <string name="chat_is_stopped">Chat je zastaven</string> - <string name="chat_database_section">CHAT DATABÁZE</string> - <string name="database_passphrase">přístupová fráze databáze</string> + <string name="chat_database_section">DATABÁZE CHATU</string> + <string name="database_passphrase">přístupová fráze k databázi</string> <string name="new_database_archive">Archiv nové databáze</string> <string name="old_database_archive">Archiv staré databáze</string> <string name="error_starting_chat">Chyba spouštění chatu</string> @@ -737,12 +734,12 @@ <string name="set_password_to_export">Nastavte přístupovou frázi pro export</string> <string name="set_password_to_export_desc">Databáze je šifrována pomocí náhodné přístupové fráze. Před exportem ji změňte.</string> <string name="error_stopping_chat">Chyba zastavování chatu</string> - <string name="import_database_question">Importovat chat databázi\?</string> + <string name="import_database_question">Importovat databázi chatu?</string> <string name="your_current_chat_database_will_be_deleted_and_replaced_with_the_imported_one">Vaše aktuální chat databáze bude SMAZÁNA a NAHRAZENA importovanou databází. \nTuto akci nelze vzít zpět - vaše profily, kontakty, zprávy a soubory budou nenávratně ztraceny.</string> - <string name="error_deleting_database">Chyba mazání chat databáze</string> - <string name="error_importing_database">Chyba importu chat databáze</string> - <string name="chat_database_deleted">Chat databáze odstraněna</string> + <string name="error_deleting_database">Chyba při mazání databáze chatu</string> + <string name="error_importing_database">Chyba při importu databáze chatu</string> + <string name="chat_database_deleted">Databáze chatu odstraněna</string> <string name="delete_files_and_media_for_all_users">Odstranit soubory všech chat profilů</string> <string name="delete_files_and_media_all">Odstranit všechny soubory</string> <string name="delete_files_and_media_desc">Tuto akci nelze vrátit zpět - všechny přijaté a odeslané soubory a média budou smazány. Obrázky s nízkým rozlišením zůstanou zachovány.</string> @@ -756,25 +753,25 @@ <string name="enable_automatic_deletion_question">Povolit automatické mazání zpráv\?</string> <string name="enable_automatic_deletion_message">Tuto akci nelze vzít zpět - zprávy odeslané a přijaté dříve, než bylo zvoleno, budou smazány. Může to trvat několik minut.</string> <string name="error_changing_message_deletion">Chyba změny nastavení</string> - <string name="save_passphrase_in_keychain">Uložit frázi do úložiště klíčů</string> - <string name="database_encrypted">Databáze šifrována!</string> - <string name="error_encrypting_database">Chyba šifrování databáze</string> + <string name="save_passphrase_in_keychain">Uložit přístupovou frázi do úložiště klíčů</string> + <string name="database_encrypted">Databáze zašifrována!</string> + <string name="error_encrypting_database">Chyba při šifrování databáze</string> <string name="encrypt_database">Šifrovat</string> <string name="encrypted_with_random_passphrase">Databáze je šifrována pomocí náhodné přístupové fráze, musíte ji změnit.</string> <string name="keychain_allows_to_receive_ntfs">K bezpečnému uložení přístupové fráze se použije úložiště klíčů Android, po restartování aplikace nebo změně přístupové fráze - umožní přijímání oznámení.</string> <string name="you_have_to_enter_passphrase_every_time">Musíte zadat přístupovou frázi při každém spuštění aplikace - není uložena v zařízení.</string> - <string name="encrypt_database_question">Šifrovat databázi\?</string> - <string name="change_database_passphrase_question">Změnit přístupovou frázi databáze\?</string> - <string name="database_will_be_encrypted">Databáze bude šifrována.</string> - <string name="database_encryption_will_be_updated">Přístupová fráze databáze bude aktualizována a uložena do úložiště klíčů.</string> - <string name="database_passphrase_will_be_updated">Přístupová fráze databáze bude aktualizována.</string> + <string name="encrypt_database_question">Zašifrovat databázi?</string> + <string name="change_database_passphrase_question">Změnit přístupovou frázi k databázi?</string> + <string name="database_will_be_encrypted">Databáze bude zašifrována.</string> + <string name="database_encryption_will_be_updated">Přístupová fráze k databázi bude aktualizována a uložena do úložiště klíčů.</string> + <string name="database_passphrase_will_be_updated">Přístupová fráze k databázi bude aktualizována.</string> <string name="store_passphrase_securely_without_recover">Uložte prosím bezpečně přístupovou frázi, pokud ji ztratíte, NEBUDE možné přistupovat k chatu.</string> <string name="wrong_passphrase">Špatná přístupová fráze k databázi</string> - <string name="encrypted_database">Šifrovaná databáze</string> + <string name="encrypted_database">Zašifrovaná databáze</string> <string name="database_error">Chyba databáze</string> <string name="keychain_error">Chyba klíčenky</string> - <string name="passphrase_is_different">Přístupová fráze databáze se liší od té uložené v klíčence.</string> - <string name="cannot_access_keychain">Nelze získat přístup ke klíčence pro uložení přístupová fráze k databázi.</string> + <string name="passphrase_is_different">Přístupová fráze k databázi se liší od té uložené v klíčence.</string> + <string name="cannot_access_keychain">Nelze získat přístup ke klíčence pro uložení přístupové fráze k databázi.</string> <string name="unknown_database_error_with_info">Neznámá chyba databáze: %s</string> <string name="wrong_passphrase_title">Špatná přístupová fráze!</string> <string name="enter_correct_passphrase">Zadejte správnou přístupovou frázi.</string> @@ -782,8 +779,8 @@ <string name="database_backup_can_be_restored">Pokus o změnu přístupové fráze databáze nebyl dokončen.</string> <string name="restore_database_alert_title">Obnovit zálohu databáze\?</string> <string name="restore_database_alert_confirm">Obnovit</string> - <string name="database_restore_error">Chyba obnovení databáze</string> - <string name="restore_passphrase_not_found_desc">Heslo nebylo v klíčence nalezeno, zadejte jej prosím ručně. K této situaci mohlo dojít, pokud jste obnovili data aplikace pomocí zálohovacího nástroje. Pokud tomu tak není, obraťte se na vývojáře.</string> + <string name="database_restore_error">Chyba při obnovování databáze</string> + <string name="restore_passphrase_not_found_desc">Přístupová fráze nebyla v klíčence nalezena, zadejte jej prosím ručně. K této situaci mohlo dojít, pokud jste obnovili data aplikace pomocí zálohovacího nástroje. Pokud tomu tak není, obraťte se na vývojáře.</string> <string name="you_can_start_chat_via_setting_or_by_restarting_the_app">Chat můžete spustit v Nastavení / Databáze nebo restartováním aplikace.</string> <string name="save_archive">Uložit archiv</string> <string name="delete_archive">Smazat archiv</string> @@ -793,7 +790,7 @@ <string name="join_group_incognito_button">Připojit se inkognito</string> <string name="joining_group">Připojit ke skupině</string> <string name="youve_accepted_group_invitation_connecting_to_inviting_group_member">Připojili jste se k této skupině. Připojení k pozvání člena skupiny.</string> - <string name="you_will_stop_receiving_messages_from_this_group_chat_history_will_be_preserved">Přestanete dostávat zprávy z této skupiny. Chat historie bude zachována.</string> + <string name="you_will_stop_receiving_messages_from_this_group_chat_history_will_be_preserved">Přestanete dostávat zprávy z této skupiny. Historie chatu bude zachována.</string> <string name="alert_title_group_invitation_expired">Platnost pozvánky vypršela!</string> <string name="alert_message_group_invitation_expired">Pozvánka do skupiny již není platná, byla odstraněna odesílatelem.</string> <string name="alert_message_no_group">Tato skupina již neexistuje.</string> @@ -828,8 +825,8 @@ <string name="group_member_status_invited">pozván</string> <string name="group_member_status_introduced">představen (zaveden)</string> <string name="group_member_status_intro_invitation">připojení (pozvánka na představení)</string> - <string name="group_member_status_accepted">připojen (přijat)</string> - <string name="group_member_status_announced">připojen (oznámen)</string> + <string name="group_member_status_accepted">připojení (přijato)</string> + <string name="group_member_status_announced">připojení (oznámeno)</string> <string name="group_member_status_connected">připojen</string> <string name="group_member_status_complete">komplet</string> <string name="group_member_status_creator">tvůrce</string> @@ -854,8 +851,8 @@ <string name="create_group_link">Vytvořit odkaz skupiny</string> <string name="delete_link">Smazat odkaz</string> <string name="you_can_share_group_link_anybody_will_be_able_to_connect">Můžete sdílet odkaz nebo QR kód - ke skupině se bude moci připojit kdokoli. O členy skupiny nepřijdete, pokud ji později odstraníte.</string> - <string name="error_creating_link_for_group">Chyba vytváření odkazu skupiny</string> - <string name="error_deleting_link_for_group">Chyba odstraňování odkazu skupiny</string> + <string name="error_creating_link_for_group">Chyba při vytváření odkazu skupiny</string> + <string name="error_deleting_link_for_group">Chyba při odstraňování odkazu skupiny</string> <string name="only_group_owners_can_change_prefs">Předvolby skupiny mohou měnit pouze vlastníci skupiny.</string> <string name="section_title_for_console">PRO KONSOLE</string> <string name="info_row_local_name">Místní název</string> @@ -867,12 +864,12 @@ <string name="change_role">Změnit roli</string> <string name="change_verb">Změnit</string> <string name="member_role_will_be_changed_with_invitation">Role bude změněna na \"%s\". Člen obdrží novou pozvánku.</string> - <string name="error_changing_role">Chyba změny role</string> + <string name="error_changing_role">Chyba při změně role</string> <string name="conn_level_desc_direct">přímo</string> - <string name="sending_via">Odesíláno přez</string> + <string name="sending_via">Odesíláno přes</string> <string name="network_status">Stav sítě</string> <string name="switch_receiving_address">Přepínač přijímací adresy</string> - <string name="group_is_decentralized">Skupina je plně decentralizovaná - viditelná pouze pro členy.</string> + <string name="group_is_decentralized">Plně decentralizovaná - viditelná pouze členům.</string> <string name="save_group_profile">Uložení profilu skupiny</string> <string name="network_options_reset_to_defaults">Obnovit výchozí nastavení</string> <string name="network_option_tcp_connection_timeout">Časový limit připojení TCP</string> @@ -881,7 +878,7 @@ <string name="network_option_ping_count">Počet PING</string> <string name="network_option_enable_tcp_keep_alive">Povolit TCP keep-alive</string> <string name="update_network_settings_confirmation">Aktualizovat</string> - <string name="users_delete_question">Smazat chat profil\?</string> + <string name="users_delete_question">Smazat profil chatu?</string> <string name="users_delete_profile_for">Smazat chat profil pro</string> <string name="users_delete_with_connections">Profil a připojení k serveru</string> <string name="users_delete_data_only">Pouze místní data profilu</string> @@ -963,7 +960,6 @@ <string name="language_system">Systém</string> <string name="smp_save_servers_question">Uložit servery\?</string> <string name="dont_show_again">Znovu neukazuj</string> - <string name="cant_delete_user_profile">Nemohu smazat uživatelský profil!</string> <string name="button_add_welcome_message">Přidat uvítací zprávu</string> <string name="v4_6_chinese_spanish_interface">Čínské a Španělské rozhranní</string> <string name="v4_6_audio_video_calls">Hlasové a video hovory</string> @@ -994,12 +990,10 @@ <string name="v4_6_audio_video_calls_descr">Podpora bluetooth a další vylepšení.</string> <string name="tap_to_activate_profile">Klepnutím aktivujete profil.</string> <string name="v4_6_chinese_spanish_interface_descr">Díky uživatelům - překládejte prostřednictvím Weblate!</string> - <string name="should_be_at_least_one_profile">Měl by tam být alespoň jeden uživatelský profil.</string> <string name="button_welcome_message">Uvítací zpráva</string> <string name="group_welcome_title">Uvítací zpráva</string> <string name="user_unmute">Zrušit ztlumení</string> <string name="to_reveal_profile_enter_password">Chcete-li odhalit svůj skrytý profil, zadejte celé heslo do vyhledávacího pole na stránce Chat profily.</string> - <string name="should_be_at_least_one_visible_profile">Měl by tam být alespoň jeden viditelný uživatelský profil.</string> <string name="you_will_still_receive_calls_and_ntfs">Stále budete přijímat volání a upozornění od umlčených profilů pokud budou aktivní.</string> <string name="you_can_hide_or_mute_user_profile">Můžete skrýt nebo ztlumit uživatelský profil - Podržte pro menu.</string> <string name="user_unhide">Odkrýt</string> @@ -1183,7 +1177,7 @@ <string name="learn_more">Zjistit více</string> <string name="share_with_contacts">Sdílet s kontakty</string> <string name="group_welcome_preview">Náhled</string> - <string name="opening_database">Otvírání databáze…</string> + <string name="opening_database">Otevírání databáze…</string> <string name="error_setting_address">Chyba nastavení adresy</string> <string name="scan_qr_to_connect_to_contact">Pro připojení může váš kontakt naskenovat QR kód, nebo použít odkaz v aplikaci.</string> <string name="you_can_accept_or_reject_connection">Když někdo požádá o připojení, můžete žádost přijmout nebo odmítnout.</string> @@ -1373,17 +1367,17 @@ <string name="privacy_show_last_messages">Zobrazit poslední zprávy</string> <string name="send_receipts_disabled_alert_msg">Tato skupina má více než %1$d členů, doručenky nejsou odeslány.</string> <string name="in_developing_desc">Tato funkce zatím není podporována. Vyzkoušejte další vydání.</string> - <string name="database_will_be_encrypted_and_passphrase_stored_in_settings">Databáze bude zašifrována a heslo bude uloženo v klíčence.</string> + <string name="database_will_be_encrypted_and_passphrase_stored_in_settings">Databáze bude zašifrována a přístupová fráze bude uloženo v klíčence.</string> <string name="socks_proxy_setting_limitations"><![CDATA[<b>Všimněte si prosím</b>: relé zpráv a souborů jsou připojeny prostřednictvím proxy SOCKS. Volání a odesílání náhledů odkazů používá přímé připojení.]]></string> <string name="encrypt_local_files">Šifrovat místní soubory</string> <string name="you_can_change_it_later">Náhodná přístupová fráze je uložena v nastavení jako prostý text. \nMůžete ji později změnit.</string> - <string name="database_encryption_will_be_updated_in_settings">Heslo pro šifrování databáze bude aktualizováno a uloženo v klíčence.</string> + <string name="database_encryption_will_be_updated_in_settings">Přístupová fráze k databáze bude aktualizována a uložena v klíčence.</string> <string name="remove_passphrase_from_settings">Odebrat přístupovou frázi z nastavení\?</string> <string name="use_random_passphrase">Použít náhodnou přístupovou frázi</string> <string name="save_passphrase_in_settings">Uložit přístupovou frázi v nastavení</string> - <string name="setup_database_passphrase">Nastavení přístupové fráze databáze</string> - <string name="set_database_passphrase">Nastavit přístupovou frázi databáze</string> + <string name="setup_database_passphrase">Nastavení přístupové fráze k databázi</string> + <string name="set_database_passphrase">Nastavit přístupovou frázi k databázi</string> <string name="open_database_folder">Otevřít složku databáze</string> <string name="passphrase_will_be_saved_in_settings">Přístupová fráze bude uložena v nastavení jako prostý text až ji změníte nebo po restartu aplikace.</string> <string name="settings_is_storing_in_clear_text">Přístupová fráze je uložena v nastavení jako prostý text.</string> @@ -1404,4 +1398,163 @@ \n- doručenky (až 20 členů). \n- rychlejší a stabilnější.</string> <string name="member_contact_send_direct_message">odeslat přímou zprávu</string> + <string name="rcv_direct_event_contact_deleted">smazaný kontakt</string> + <string name="error_alert_title">Chyba</string> + <string name="create_another_profile_button">Vytvořit profil</string> + <string name="connected_desktop">Připojený počítač</string> + <string name="group_members_2">%s a %s</string> + <string name="multicast_connect_automatically">Připojit se automaticky</string> + <string name="desktop_address">Adresa počítače</string> + <string name="connect_plan_join_your_group">Připojit se do skupiny?</string> + <string name="connect_plan_group_already_exists">Skupina již existuje!</string> + <string name="rcv_group_event_1_member_connected">%s připojený</string> + <string name="this_device">Toto zařízení</string> + <string name="desktop_device">Počítač</string> + <string name="this_device_name">Jméno tohoto zařízení</string> + <string name="found_desktop">Počítač nalezen</string> + <string name="delete_messages__question">Smazat %d zpráv?</string> + <string name="remove_member_button">Odebrat člena</string> + <string name="connected_mobile">Připojený telefon</string> + <string name="button_remove_member_question">Odebrat člena?</string> + <string name="connect_plan_open_group">Otevřít skupinu</string> + <string name="desktop_connection_terminated">Spojení ukončeno</string> + <string name="error">Chyba</string> + <string name="connect_to_desktop">Připojit se k počítači</string> + <string name="disconnect_remote_host">Odpojit</string> + <string name="invalid_name">Neplatné jméno!</string> + <string name="group_member_role_author">Autor</string> + <string name="connected_to_mobile">Připojený k telefonu</string> + <string name="bad_desktop_address">Špatná adresa počítače</string> + <string name="devices">Zařízení</string> + <string name="disconnect_desktop_question">Odpojit počítač?</string> + <string name="create_group_button">Vytvořit skupinu</string> + <string name="session_code">Kód relace</string> + <string name="paste_desktop_address">Vložit adres počítače</string> + <string name="blocked_item_description">Blokovaný</string> + <string name="v5_4_better_groups">Lepší skupiny</string> + <string name="expand_verb">Rozbalit</string> + <string name="v5_4_block_group_members">Blokovat členy skupin</string> + <string name="connect_plan_repeat_connection_request">Opakovat žádost o připojení?</string> + <string name="encryption_renegotiation_error">Chyba opětovného vyjednávání šifrování</string> + <string name="connect_plan_you_are_already_connecting_to_vName">Již se připojujete k %1$s.</string> + <string name="v5_4_incognito_groups_descr">Vytvořit skupinu pomocí náhodného profilu.</string> + <string name="connect_plan_you_are_already_joining_the_group_via_this_link">Již se připojujete ke skupině prostřednictvím tohoto odkazu.</string> + <string name="refresh_qr_code">Obnovit</string> + <string name="new_mobile_device">Nový telefon</string> + <string name="only_one_device_can_work_at_the_same_time">Pouze jedno zařízení může pracovat současně</string> + <string name="you_can_make_address_visible_via_settings">Můžete ji svým SimpleX kontaktům zviditelnit v Nastavení.</string> + <string name="connect_plan_you_are_already_joining_the_group_vName">Již se připojujete ke skupině %1$s.</string> + <string name="v5_4_link_mobile_desktop">Připojit mobilní a stolní aplikace! 🔗</string> + <string name="connect_plan_this_is_your_own_one_time_link">To je váš vlastní jednorázový odkaz!</string> + <string name="marked_deleted_items_description">%d zpráv označeno jako smazaná</string> + <string name="v5_4_link_mobile_desktop_descr">Prostřednictvím zabezpečeného kvant rezistentního protokolu.</string> + <string name="open_on_mobile_and_scan_qr_code"><![CDATA[Otevřete <i>Použijte z PC</i> v aplikaci telefonu a naskenujte QR kód.]]></string> + <string name="connect_plan_already_connecting">Již připojuji!</string> + <string name="v5_4_block_group_members_descr">Skrýt nežádoucí zprávy.</string> + <string name="desktop_incompatible_version">Nekompatibilní verze</string> + <string name="new_desktop"><![CDATA[<i>(nový)</i>]]></string> + <string name="unlink_desktop_question">Odpojit PC?</string> + <string name="linked_desktop_options">Možnosti připojeného PC</string> + <string name="video_decoding_exception_desc">Video nelze dekódovat. +\nProsím vyzkoušejte jiné video, nebo kontaktujte vývojáře.</string> + <string name="random_port">Náhodný</string> + <string name="linked_desktops">Připojená PC</string> + <string name="discover_on_network">Objevit přes lokální síť</string> + <string name="rcv_group_and_other_events">a %d jiných událostí</string> + <string name="connect_plan_connect_via_link">Připojit přez odkaz?</string> + <string name="v5_4_incognito_groups">Inkognito skupiny</string> + <string name="connect_plan_already_joining_the_group">Už se ke skupině připojujete!</string> + <string name="group_members_n">%s, %s a %d členů</string> + <string name="moderated_items_description">%1$d zpráv moderoval %2$s</string> + <string name="unblock_member_button">Odblokovat člena</string> + <string name="remote_host_was_disconnected_toast"><![CDATA[Telefon <b>%s</b> byl odpojen]]></string> + <string name="waiting_for_desktop">Čekání na PC…</string> + <string name="v5_4_better_groups_descr">Rychlejší připojování a spolehlivější zprávy.</string> + <string name="error_showing_content">chyba zobrazení obsahu</string> + <string name="connect_plan_connect_to_yourself">Připojit se k sobě?</string> + <string name="linked_mobiles">Připojené telefony</string> + <string name="connected_to_desktop">Připojeno k PC</string> + <string name="contact_tap_to_connect">Klepněte na Připojit se</string> + <string name="connect_plan_you_are_already_in_group_vName">Již jste ve skupině %1$s.</string> + <string name="connect_plan_this_is_your_own_simplex_address">To je vaše vlastní SimpleX adresa!</string> + <string name="loading_remote_file_title">Načítám soubor</string> + <string name="connecting_to_desktop">Připojuji k PC</string> + <string name="alert_text_encryption_renegotiation_failed">Opětovné vyjednávání šifrování selhalo.</string> + <string name="error_showing_message">chyba zobrazení zprávy</string> + <string name="desktop_devices">PC</string> + <string name="correct_name_to">Upravit jméno na %s?</string> + <string name="not_compatible">Nekompatibilní!</string> + <string name="waiting_for_mobile_to_connect">Čekání na připojení telefonu:</string> + <string name="link_a_mobile">Připojit telefon</string> + <string name="connect_with_contact_name_question">Připojit s %1$s?</string> + <string name="block_member_confirmation">Blokovat</string> + <string name="unblock_member_question">Odblokovat člena?</string> + <string name="blocked_items_description">%d zpráv zablokováno</string> + <string name="open_port_in_firewall_desc">Chcete-li povolit telefonu připojení k PC, otevřete tento port ve vašem firewallu, pokud je povolen</string> + <string name="block_member_button">Blokovat člena</string> + <string name="settings_section_title_use_from_desktop">Použít z PC</string> + <string name="connect_plan_repeat_join_request">Opakovat požadavek na připojení?</string> + <string name="create_chat_profile">Vytvořit chat profil</string> + <string name="app_was_crashed">Zobrazit havarované</string> + <string name="delete_and_notify_contact">Smazat a informovat kontakt</string> + <string name="connect_plan_you_are_already_connecting_via_this_one_time_link">Již se připojujete přes tento jednorázový odkaz!</string> + <string name="this_device_version"><![CDATA[<i>(toto zařízení v%s)</i>]]></string> + <string name="unlink_desktop">Odpojit</string> + <string name="unblock_member_desc">Zprávy od %s budou zobrazeny!</string> + <string name="this_device_name_shared_with_mobile">Název zařízení bude sdílen s připojeným mobilním klientem.</string> + <string name="error_sending_message_contact_invitation">Chyba odesílání pozvánky</string> + <string name="verify_code_on_mobile">Ověřit kód v telefonu</string> + <string name="open_port_in_firewall_title">Otevřít port ve firewallu</string> + <string name="enter_this_device_name">Zadejte jméno tohoto zařízení…</string> + <string name="non_content_uri_alert_text">Sdílíte neplatnou cestu souboru. Nahlaste problém vývojářům aplikace.</string> + <string name="disconnect_remote_hosts">Odpojit mobilní telefony</string> + <string name="block_member_question">Blokovat člena?</string> + <string name="rcv_group_events_count">%d skupinových událostí</string> + <string name="connect_plan_this_is_your_link_for_group_vName">To je váš odkaz pro skupinu %1$s!</string> + <string name="verify_code_with_desktop">Ověřit kód s PC</string> + <string name="scan_qr_code_from_desktop">Skenovat QR kód z PC</string> + <string name="unblock_member_confirmation">Odblokovat</string> + <string name="multicast_discoverable_via_local_network">Objevitelný prostřednictvím lokální sítě</string> + <string name="v5_4_more_things_descr">- volitelně oznámení odstraněným kontaktům. +\n- profilová jména s mezeramy. +\n- a více!</string> + <string name="non_content_uri_alert_title">Neplatná cesta souboru</string> + <string name="connect_plan_you_have_already_requested_connection_via_this_address">Již jste požádali o spojení přes tuto adresu!</string> + <string name="terminal_always_visible">Zobrazit konzoli v novém okně</string> + <string name="scan_from_mobile">Skenování z telefonu</string> + <string name="verify_connections">Ověřit více připojení</string> + <string name="loading_remote_file_desc">Prosím počkejte, než bude soubor načten z propojeného telefonu</string> + <string name="block_member_desc">Všechny nové zprávy od %s budou skryté!</string> + <string name="desktop_app_version_is_incompatible">Verze aplikace na PC %s není kompatibilní s touto aplikací.</string> + <string name="verify_connection">Ověřit připojení</string> + <string name="no_connected_mobile">Žádný připojený telefon</string> + <string name="loading_chats">Nahrávám chat..</string> + <string name="search_or_paste_simplex_link">Hledat nebo vložit SimpleX odkaz</string> + <string name="camera_not_available">Kamera není k dispozici</string> + <string name="enable_camera_access">Povolit fotoaparát</string> + <string name="tap_to_scan">Klepnutím skenovat</string> + <string name="create_group_button_to_create_new_group"><![CDATA[<b>Vytvořit skupinu</b>: vytvořit novou skupinu.]]></string> + <string name="add_contact_button_to_create_link_or_connect_via_link"><![CDATA[<b>Přidat kontakt</b>: vytvořit novou pozvánku nebo připojit přes odkaz, který jste obdrželi.]]></string> + <string name="add_contact_tab">Přidat kontakt</string> + <string name="new_chat">Nový chat</string> + <string name="creating_link">Vytvořit odkaz…</string> + <string name="keep_invitation_link">Ponechat</string> + <string name="keep_unused_invitation_question">Ponechat nepoužitou pozvánku?</string> + <string name="or_scan_qr_code">Nebo skenovat QR kód</string> + <string name="or_show_this_qr_code">Nebo ukázat tento kód</string> + <string name="you_can_view_invitation_link_again">Pozvánku můžete znovu zobrazit v detailech připojení.</string> + <string name="invalid_qr_code">Neplatný QR kód</string> + <string name="retry_verb">Zkusit znovu</string> + <string name="share_this_1_time_link">Sdílejte tento jedorázový odkaz</string> + <string name="tap_to_paste_link">Klepnutím vložte odkaz</string> + <string name="code_you_scanned_is_not_simplex_link_qr_code">Kód který jste naskenovali, není SimpleX QR odkaz.</string> + <string name="the_text_you_pasted_is_not_a_link">Text který jste vložili, není SimpleX odkaz.</string> + <string name="recent_history">Viditelná historie</string> + <string name="disable_sending_recent_history">Nezasílat historii novým členům.</string> + <string name="la_app_passcode">Heslo aplikace</string> + <string name="start_chat_question">Začít chat?</string> + <string name="enable_sending_recent_history">Odešlete až 100 posledních zpráv novým členům.</string> + <string name="recent_history_is_not_sent_to_new_members">Historie není odeslána novým členům.</string> + <string name="recent_history_is_sent_to_new_members">Až 100 poslední zprávy je odesláno novým členům.</string> + <string name="chat_is_stopped_you_should_transfer_database">Chat je zastaven. Pokud jste již použili tuto databázi na jiném zařízení, měli byste ji před zahájením chatu převést zpět.</string> </resources> \ No newline at end of file diff --git a/apps/multiplatform/common/src/commonMain/resources/MR/de/strings.xml b/apps/multiplatform/common/src/commonMain/resources/MR/de/strings.xml index a36eca6663..836671ad48 100644 --- a/apps/multiplatform/common/src/commonMain/resources/MR/de/strings.xml +++ b/apps/multiplatform/common/src/commonMain/resources/MR/de/strings.xml @@ -3,8 +3,8 @@ <string name="app_name">SimpleX</string> <string name="thousand_abbreviation">k</string> <!-- Connect via Link - MainActivity.kt --> - <string name="connect_via_contact_link">Über die Kontakt-Adresse verbinden?</string> - <string name="connect_via_invitation_link">Über den Einmal-Link verbinden?</string> + <string name="connect_via_contact_link">Über den Kontaktadressen-Link verbinden?</string> + <string name="connect_via_invitation_link">Über den Einmal-Einladungslink verbinden?</string> <string name="connect_via_group_link">Der Gruppe beitreten?</string> <string name="profile_will_be_sent_to_contact_sending_link">Ihr Profil wird an den Kontakt gesendet, von dem Sie diesen Link erhalten haben.</string> <string name="you_will_join_group">Sie werden mit allen Gruppenmitgliedern verbunden.</string> @@ -21,9 +21,9 @@ <string name="marked_deleted_description">als gelöscht markiert</string> <string name="sending_files_not_yet_supported">Das Senden von Dateien wird noch nicht unterstützt</string> <string name="receiving_files_not_yet_supported">Der Empfang von Dateien wird noch nicht unterstützt</string> - <string name="sender_you_pronoun">Ihre Daten</string> + <string name="sender_you_pronoun">Profil</string> <string name="unknown_message_format">Unbekanntes Nachrichtenformat</string> - <string name="invalid_message_format">Unzulässiges Nachrichtenformat</string> + <string name="invalid_message_format">Ungültiges Nachrichtenformat</string> <!-- PendingContactConnection - ChatModel.kt --> <string name="connection_local_display_name">verbindung %1$d</string> <string name="display_name_connection_established">verbindung hergestellt</string> @@ -39,7 +39,7 @@ <string name="description_via_one_time_link_incognito">Inkognito über einen Einmal-Link</string> <!-- FormattedText, SimpleX links - ChatModel.kt --> <string name="simplex_link_contact">SimpleX-Kontaktadressen-Link</string> - <string name="simplex_link_invitation">SimpleX-Einmal-Einladung</string> + <string name="simplex_link_invitation">SimpleX-Einmal-Einladungslink</string> <string name="simplex_link_group">SimpleX-Gruppen-Link</string> <string name="simplex_link_connection">über %1$s</string> <string name="simplex_link_mode">SimpleX-Links</string> @@ -75,7 +75,7 @@ <string name="error_deleting_group">Fehler beim Löschen der Gruppe</string> <string name="error_deleting_contact_request">Fehler beim Löschen der Kontaktanfrage</string> <string name="error_deleting_pending_contact_connection">Fehler beim Löschen der anstehenden Kontaktaufnahme</string> - <string name="error_changing_address">Fehler beim Wechseln der Adresse</string> + <string name="error_changing_address">Fehler beim Wechseln der Empfängeradresse</string> <string name="error_smp_test_failed_at_step">Der Test ist beim Schritt %s fehlgeschlagen.</string> <string name="error_smp_test_server_auth">Um Warteschlangen zu erzeugen, benötigt der Server eine Authentifizierung. Bitte überprüfen Sie das Passwort.</string> <string name="error_smp_test_certificate">Der Fingerabdruck des Zertifikats in der Serveradresse ist wahrscheinlich ungültig.</string> @@ -98,7 +98,7 @@ <string name="enter_passphrase_notification_title">Passwort wird benötigt</string> <string name="enter_passphrase_notification_desc">Geben Sie bitte das Datenbank-Passwort ein, um Benachrichtigungen zu erhalten.</string> <string name="database_initialization_error_title">Die Datenbank kann nicht initialisiert werden</string> - <string name="database_initialization_error_desc">Die Datenbank arbeitet nicht richtig. Tippen Sie für weitere Informationen.</string> + <string name="database_initialization_error_desc">Die Datenbank arbeitet nicht richtig. Für weitere Informationen antippen.</string> <!-- SimpleX Chat foreground Service --> <string name="simplex_service_notification_title">SimpleX-Chat-Hintergrunddienst</string> <string name="simplex_service_notification_text">Empfange Nachrichten …</string> @@ -176,7 +176,7 @@ <string name="group_preview_you_are_invited">Sie sind zu der Gruppe eingeladen</string> <string name="group_preview_join_as">Beitreten als %s</string> <string name="group_connection_pending">verbinde …</string> - <string name="tap_to_start_new_chat">Tippen Sie, um einen neuen Chat zu starten</string> + <string name="tap_to_start_new_chat">Zum Starten eines neuen Chats tippen</string> <string name="chat_with_developers">Chatten Sie mit den Entwicklern</string> <string name="you_have_no_chats">Sie haben keine Chats</string> <!-- ShareListView.kt --> @@ -262,16 +262,14 @@ <string name="gallery_video_button">Video</string> <!-- help - ChatHelpView.kt --> <string name="thank_you_for_installing_simplex">Danke, dass Sie SimpleX Chat installiert haben!</string> - <string name="you_can_connect_to_simplex_chat_founder"><![CDATA[Sie können sich <font color=#0088ff>mit SimpleX-Chat-Entwicklern verbinden, um Fragen zu stellen und Updates zu erhalten</font>.]]></string> + <string name="you_can_connect_to_simplex_chat_founder"><![CDATA[Sie können sich <font color="#0088ff">mit SimpleX-Chat-Entwicklern verbinden, um Fragen zu stellen und Updates zu erhalten</font>.]]></string> <string name="to_start_a_new_chat_help_header">Um einen neuen Chat zu starten</string> <string name="chat_help_tap_button">Schaltfläche antippen</string> <string name="above_then_preposition_continuation">Danach die gewünschte Aktion auswählen:</string> - <string name="add_new_contact_to_create_one_time_QR_code"><![CDATA[<b>Neuen Kontakt hinzufügen</b>: Um Ihren Einmal-QR-Code für Ihren Kontakt zu erstellen.]]></string> - <string name="scan_QR_code_to_connect_to_contact_who_shows_QR_code"><![CDATA[<b>QR-Code scannen</b>: Um sich mit Ihrem Kontakt zu verbinden, der Ihnen seinen QR-Code zeigt.]]></string> <string name="to_connect_via_link_title">Über Link verbinden</string> <string name="if_you_received_simplex_invitation_link_you_can_open_in_browser">Wenn Sie einen SimpleX-Chat-Einladungslink erhalten haben, können Sie ihn in Ihrem Browser öffnen:</string> <string name="desktop_scan_QR_code_from_app_via_scan_QR_code"><![CDATA[💻 Desktop: Angezeigten QR-Code aus der App scannen, über <b>QR-Code scannen</b>.]]></string> - <string name="mobile_tap_open_in_mobile_app_then_tap_connect_in_app"><![CDATA[📱 Handy: Tippen Sie in der App auf „<b>In mobiler App öffnen</b>“ und dann auf „<b>Verbinden</b>“.]]></string> + <string name="mobile_tap_open_in_mobile_app_then_tap_connect_in_app"><![CDATA[📱 Mobiltelefon: Tippen Sie in der App auf „<b>In mobiler App öffnen</b>“ und dann auf „<b>Verbinden</b>“.]]></string> <!-- Contact Request Alert Dialogue - ChatListNavLinkView.kt --> <string name="accept_connection_request__question">Die Verbindungsanfrage akzeptieren?</string> <string name="if_you_choose_to_reject_the_sender_will_not_be_notified">Wenn Sie ablehnen, wird der Absender NICHT benachrichtigt.</string> @@ -333,7 +331,7 @@ <string name="your_chat_profile_will_be_sent_to_your_contact">Ihr Chat-Profil wird \nan Ihren Kontakt gesendet</string> <string name="if_you_cannot_meet_in_person_scan_QR_in_video_call_or_ask_for_invitation_link"><![CDATA[Wenn Sie sich nicht persönlich treffen können, können Sie <b>den QR-Code während eines Videoanrufs scannen</b> oder Ihr Kontakt kann einen Einladungslink über einen anderen Kanal mit Ihnen teilen.]]></string> - <string name="share_invitation_link">Einmal-Link teilen</string> + <string name="share_invitation_link">Einmal-Einladungslink teilen</string> <!-- PasteToConnect.kt --> <string name="connect_via_link">Über einen Link verbinden</string> <string name="connect_button">Verbinden</string> @@ -341,10 +339,9 @@ <string name="this_string_is_not_a_connection_link">Diese Zeichenfolge entspricht keinem gültigen Verbindungslink!</string> <string name="you_can_also_connect_by_clicking_the_link"><![CDATA[Sie können sich auch verbinden, indem Sie auf den Link klicken. Wenn er im Browser geöffnet wird, klicken Sie auf die Schaltfläche „<b>In mobiler App öffnen</b>“.]]></string> <!-- CreateLinkView.kt --> - <string name="create_one_time_link">Einmal-Einladungslink erstellen</string> <string name="one_time_link">Einmal-Einladungslink</string> <!-- settings - SettingsView.kt --> - <string name="your_settings">Ihre Einstellungen</string> + <string name="your_settings">Einstellungen</string> <string name="your_simplex_contact_address">Ihre SimpleX-Adresse</string> <string name="database_passphrase_and_export">Datenbank-Passwort & -Export</string> <string name="about_simplex_chat">Über SimpleX Chat</string> @@ -389,7 +386,7 @@ <string name="configure_ICE_servers">ICE-Server konfigurieren</string> <string name="enter_one_ICE_server_per_line">ICE-Server (einer pro Zeile)</string> <string name="error_saving_ICE_servers">Fehler beim Speichern der ICE-Server</string> - <string name="ensure_ICE_server_address_are_correct_format_and_unique">Stellen Sie sicher, dass die WebRTC-ICE-Server-Adressen das richtige Format haben, zeilenweise separiert und nicht doppelt vorhanden sind.</string> + <string name="ensure_ICE_server_address_are_correct_format_and_unique">Stellen Sie sicher, dass die WebRTC-ICE-Server-Adressen das richtige Format haben, zeilenweise getrennt und nicht doppelt vorhanden sind.</string> <string name="save_servers_button">Speichern</string> <string name="network_and_servers">Netzwerk & Server</string> <string name="network_settings">Erweiterte Netzwerkeinstellungen</string> @@ -674,7 +671,7 @@ <string name="database_restore_error">Fehler bei der Wiederherstellung der Datenbank</string> <string name="restore_passphrase_not_found_desc">Das Passwort wurde nicht im Schlüsselbund gefunden. Bitte geben Sie es manuell ein. Das kann passieren, wenn Sie die App-Daten mit einem Backup-Programm wieder hergestellt haben. Bitte nehmen Sie Kontakt mit den Entwicklern auf, wenn das nicht der Fall ist.</string> <!-- ChatModel.chatRunning interactions --> - <string name="chat_is_stopped_indication">Chat wurde beendet</string> + <string name="chat_is_stopped_indication">Der Chat wurde beendet</string> <string name="you_can_start_chat_via_setting_or_by_restarting_the_app">Sie können den Chat über die App-Einstellungen/Datenbank oder durch Neustart der App starten.</string> <!-- ChatArchiveView.kt --> <string name="chat_archive_header">Datenbank-Archiv</string> @@ -693,10 +690,10 @@ <string name="youve_accepted_group_invitation_connecting_to_inviting_group_member">Sie sind dieser Gruppe beigetreten. Sie werden mit dem einladenden Gruppenmitglied verbunden.</string> <string name="leave_group_button">Verlassen</string> <string name="leave_group_question">Die Gruppe verlassen?</string> - <string name="you_will_stop_receiving_messages_from_this_group_chat_history_will_be_preserved">Sie werden von dieser Gruppe keine Nachrichten mehr erhalten. Der Chatverlauf wird beibehalten.</string> + <string name="you_will_stop_receiving_messages_from_this_group_chat_history_will_be_preserved">Sie werden von dieser Gruppe keine Nachrichten mehr erhalten. Der Nachrichtenverlauf wird beibehalten.</string> <string name="icon_descr_add_members">Mitglieder einladen</string> <string name="icon_descr_group_inactive">Gruppe inaktiv</string> - <string name="alert_title_group_invitation_expired">Einladung abgelaufen!</string> + <string name="alert_title_group_invitation_expired">Die Einladung ist abgelaufen!</string> <string name="alert_message_group_invitation_expired">Die Gruppeneinladung ist nicht mehr gültig, da sie vom Absender entfernt wurde.</string> <string name="alert_title_no_group">Die Gruppe wurde nicht gefunden!</string> <string name="alert_message_no_group">Diese Gruppe existiert nicht mehr.</string> @@ -706,7 +703,7 @@ <string name="you_sent_group_invitation">Sie haben eine Gruppeneinladung gesendet</string> <string name="you_are_invited_to_group">Sie sind zu der Gruppe eingeladen</string> <string name="group_invitation_tap_to_join">Zum Beitreten tippen</string> - <string name="group_invitation_tap_to_join_incognito">Tippen, um Inkognito beizutreten</string> + <string name="group_invitation_tap_to_join_incognito">Zum Inkognito beitreten tippen</string> <string name="you_joined_this_group">Sie sind dieser Gruppe beigetreten</string> <string name="you_rejected_group_invitation">Sie haben die Gruppeneinladung abgelehnt</string> <string name="group_invitation_expired">Die Gruppeneinladung ist abgelaufen</string> @@ -727,12 +724,12 @@ <string name="snd_group_event_user_left">hat die Gruppe verlassen</string> <string name="snd_group_event_group_profile_updated">Gruppenprofil aktualisiert</string> <!-- Conn event chat items --> - <string name="rcv_conn_event_switch_queue_phase_completed">wechselte die Adresse für Sie</string> - <string name="rcv_conn_event_switch_queue_phase_changing">Wechsel der Adresse…</string> - <string name="snd_conn_event_switch_queue_phase_completed_for_member">Sie haben die Adresse für %s gewechselt</string> - <string name="snd_conn_event_switch_queue_phase_changing_for_member">Wechsel der Adresse für %s…</string> - <string name="snd_conn_event_switch_queue_phase_completed">Sie haben die Adresse gewechselt</string> - <string name="snd_conn_event_switch_queue_phase_changing">Wechsel der Adresse…</string> + <string name="rcv_conn_event_switch_queue_phase_completed">wechselte die Empfängeradresse für Sie</string> + <string name="rcv_conn_event_switch_queue_phase_changing">Wechsel der Empfängeradresse wurde gestartet…</string> + <string name="snd_conn_event_switch_queue_phase_completed_for_member">Die Empfängeradresse für %s wurde gewechselt</string> + <string name="snd_conn_event_switch_queue_phase_changing_for_member">Wechsel der Empfängeradresse für %s wurde gestartet…</string> + <string name="snd_conn_event_switch_queue_phase_completed">Die Empfängeradresse wurde gewechselt</string> + <string name="snd_conn_event_switch_queue_phase_changing">Wechsel der Empfängeradresse wurde gestartet…</string> <!-- GroupMemberRole --> <string name="group_member_role_member">Mitglied</string> <string name="group_member_role_admin">Admin</string> @@ -870,15 +867,15 @@ <string name="feature_enabled_for_contact">Für Kontakt aktiviert</string> <string name="feature_off">Aus</string> <string name="feature_received_prohibited">empfangen, nicht erlaubt</string> - <string name="allow_your_contacts_irreversibly_delete">Erlauben Sie Ihren Kontakten gesendete Nachrichten unwiederbringlich zu löschen.</string> - <string name="allow_irreversible_message_deletion_only_if">Erlauben Sie das unwiederbringliche Löschen von Nachrichten nur dann, wenn es Ihr Kontakt ebenfalls erlaubt.</string> + <string name="allow_your_contacts_irreversibly_delete">Erlauben Sie Ihren Kontakten gesendete Nachrichten unwiederbringlich zu löschen (bis zu 24 Stunden).</string> + <string name="allow_irreversible_message_deletion_only_if">Erlauben Sie das unwiederbringliche Löschen von Nachrichten nur dann, wenn es Ihr Kontakt ebenfalls erlaubt (bis zu 24 Stunden).</string> <string name="contacts_can_mark_messages_for_deletion">Ihre Kontakte können Nachrichten zum Löschen markieren. Sie können diese Nachrichten trotzdem anschauen.</string> <string name="allow_your_contacts_to_send_voice_messages">Erlauben Sie Ihre Kontakten Sprachnachrichten zu versenden.</string> <string name="allow_voice_messages_only_if">Erlauben Sie Sprachnachrichten nur dann, wenn es Ihr Kontakt ebenfalls erlaubt.</string> <string name="prohibit_sending_voice_messages">Das Senden von Sprachnachrichten nicht erlauben.</string> - <string name="both_you_and_your_contacts_can_delete">Sowohl Ihr Kontakt als auch Sie können Nachrichten unwiederbringlich löschen.</string> - <string name="only_you_can_delete_messages">Nur Sie können Nachrichten unwiederbringlich löschen (Ihr Kontakt kann sie zum Löschen markieren).</string> - <string name="only_your_contact_can_delete">Nur Ihr Kontakt kann Nachrichten unwiederbringlich löschen (Sie können sie zum Löschen markieren).</string> + <string name="both_you_and_your_contacts_can_delete">Sowohl Ihr Kontakt als auch Sie können Nachrichten unwiederbringlich löschen (bis zu 24 Stunden).</string> + <string name="only_you_can_delete_messages">Nur Sie können Nachrichten unwiederbringlich löschen (Ihr Kontakt kann sie zum Löschen markieren) (bis zu 24 Stunden).</string> + <string name="only_your_contact_can_delete">Nur Ihr Kontakt kann Nachrichten unwiederbringlich löschen (Sie können sie zum Löschen markieren) (bis zu 24 Stunden).</string> <string name="message_deletion_prohibited">In dieser Gruppe ist das unwiederbringliche Löschen von Nachrichten nicht erlaubt.</string> <string name="both_you_and_your_contact_can_send_voice">Sowohl Ihr Kontakt als auch Sie können Sprachnachrichten versenden.</string> <string name="only_you_can_send_voice">Nur Sie können Sprachnachrichten versenden.</string> @@ -886,13 +883,13 @@ <string name="voice_prohibited_in_this_chat">In diesem Chat sind Sprachnachrichten nicht erlaubt.</string> <string name="allow_direct_messages">Das Senden von Direktnachrichten an Gruppenmitglieder erlauben.</string> <string name="prohibit_direct_messages">Das Senden von Direktnachrichten an Gruppenmitglieder nicht erlauben.</string> - <string name="allow_to_delete_messages">Unwiederbringliches löschen von gesendeten Nachrichten erlauben.</string> + <string name="allow_to_delete_messages">Unwiederbringliches löschen von gesendeten Nachrichten erlauben (bis zu 24 Stunden).</string> <string name="prohibit_message_deletion">Unwiederbringliches Löschen von Nachrichten nicht erlauben.</string> <string name="allow_to_send_voice">Das Senden von Sprachnachrichten erlauben.</string> <string name="prohibit_sending_voice">Das Senden von Sprachnachrichten nicht erlauben.</string> <string name="group_members_can_send_dms">Gruppenmitglieder können Direktnachrichten versenden.</string> <string name="direct_messages_are_prohibited_in_chat">In dieser Gruppe sind Direktnachrichten zwischen Mitgliedern nicht erlaubt.</string> - <string name="group_members_can_delete">Gruppenmitglieder können gesendete Nachrichten unwiederbringlich löschen.</string> + <string name="group_members_can_delete">Gruppenmitglieder können gesendete Nachrichten unwiederbringlich löschen (bis zu 24 Stunden).</string> <string name="message_deletion_prohibited_in_chat">In dieser Gruppe ist das unwiederbringliche Löschen von Nachrichten nicht erlaubt.</string> <string name="group_members_can_send_voice">Gruppenmitglieder können Sprachnachrichten versenden.</string> <string name="voice_messages_are_prohibited">In dieser Gruppe sind Sprachnachrichten nicht erlaubt.</string> @@ -996,7 +993,7 @@ <string name="users_delete_profile_for">Chat-Profil löschen für</string> <string name="network_option_ping_count">PING-Zähler</string> <string name="update_network_session_mode_question">Transport-Isolations-Modus aktualisieren\?</string> - <string name="smp_servers_per_user">Server der neuen Verbindungen von Ihrem aktuellen Chat-Profil</string> + <string name="smp_servers_per_user">Mögliche Server für neue Verbindungen über Ihr aktuelles Chat-Profil</string> <string name="files_and_media_section">Dateien & Medien</string> <string name="network_session_mode_transport_isolation">Transport-Isolation</string> <string name="users_delete_question">Chat-Profil löschen\?</string> @@ -1044,7 +1041,6 @@ <string name="moderate_message_will_be_deleted_warning">Diese Nachricht wird für alle Gruppenmitglieder gelöscht.</string> <string name="language_system">System</string> <string name="confirm_password">Passwort bestätigen</string> - <string name="cant_delete_user_profile">Das Benutzerprofil kann nicht gelöscht werden!</string> <string name="dont_show_again">Nicht nochmals anzeigen</string> <string name="v4_6_chinese_spanish_interface">Chinesische und spanische Bedienoberfläche</string> <string name="v4_6_audio_video_calls">Audio- und Videoanrufe</string> @@ -1062,9 +1058,7 @@ <string name="enter_password_to_show">Für die Anzeige das Passwort im Suchfeld eingeben</string> <string name="make_profile_private">Privates Profil erzeugen!</string> <string name="user_mute">Stummschalten</string> - <string name="tap_to_activate_profile">Tippen Sie auf das Profil, um es zu aktivieren.</string> - <string name="should_be_at_least_one_profile">Es muss mindestens ein Benutzer-Profil vorhanden sein.</string> - <string name="should_be_at_least_one_visible_profile">Es muss mindestens ein sichtbares Benutzer-Profil vorhanden sein.</string> + <string name="tap_to_activate_profile">Zum Aktivieren des Profils tippen.</string> <string name="user_unmute">Stummschaltung aufheben</string> <string name="muted_when_inactive">Bei Inaktivität stummgeschaltet!</string> <string name="v4_6_hidden_chat_profiles_descr">Schützen Sie Ihre Chat-Profile mit einem Passwort!</string> @@ -1157,7 +1151,7 @@ <string name="alert_title_msg_bad_hash">Ungültiger Nachrichten-Hash</string> <string name="la_auth_failed">Authentifizierung fehlgeschlagen</string> <string name="alert_title_msg_bad_id">Falsche Nachrichten-ID</string> - <string name="ensure_xftp_server_address_are_correct_format_and_unique">Stellen Sie sicher, dass die XFTP-Server-Adressen das richtige Format haben, zeilenweise separiert und nicht doppelt vorhanden sind.</string> + <string name="ensure_xftp_server_address_are_correct_format_and_unique">Stellen Sie sicher, dass die XFTP-Server-Adressen das richtige Format haben, zeilenweise getrennt und nicht doppelt vorhanden sind.</string> <string name="network_socks_toggle_use_socks_proxy">SOCKS-Proxy nutzen</string> <string name="la_lock_mode">SimpleX-Sperrmodus</string> <string name="lock_not_enabled">SimpleX-Sperre ist nicht aktiviert!</string> @@ -1212,10 +1206,10 @@ <string name="scan_qr_to_connect_to_contact">Um eine Verbindung herzustellen, kann Ihr Kontakt den QR-Code scannen oder den Link in der App verwenden.</string> <string name="simplex_address">SimpleX-Adresse</string> <string name="you_can_accept_or_reject_connection">Wenn Personen eine Verbindung anfordern, können Sie diese annehmen oder ablehnen.</string> - <string name="you_wont_lose_your_contacts_if_delete_address">Sie werden Ihre Kontakte nicht verlieren, falls Sie Ihre Adresse später löschen.</string> + <string name="you_wont_lose_your_contacts_if_delete_address">Sie werden Ihre damit verbundenen Kontakte nicht verlieren, wenn Sie diese Adresse später löschen.</string> <string name="customize_theme_title">Design anpassen</string> <string name="theme_colors_section_title">DESIGN-FARBEN</string> - <string name="add_address_to_your_profile">Fügen Sie die Adresse zu Ihrem Profil hinzu, damit Ihre Kontakte sie mit anderen Personen teilen können. Es wird eine Profilaktualisierung an Ihre Kontakte gesendet.</string> + <string name="add_address_to_your_profile">Fügen Sie die Adresse Ihrem Profil hinzu, damit Ihre Kontakte sie mit anderen Personen teilen können. Es wird eine Profilaktualisierung an Ihre Kontakte gesendet.</string> <string name="all_your_contacts_will_remain_connected_update_sent">Alle Ihre Kontakte bleiben verbunden. Es wird eine Profilaktualisierung an Ihre Kontakte gesendet.</string> <string name="create_address_and_let_people_connect">Erstellen Sie eine Adresse, damit sich Personen mit Ihnen verbinden können.</string> <string name="create_simplex_address">SimpleX-Adresse erstellen</string> @@ -1319,7 +1313,7 @@ <string name="custom_time_unit_hours">Stunden</string> <string name="v5_1_better_messages_descr">- Bis zu 5 Minuten lange Sprachnachrichten \n- Zeitdauer für verschwindende Nachrichten anpassen -\n- Nachrichten-Historie bearbeiten</string> +\n- Nachrichtenverlauf bearbeiten</string> <string name="custom_time_picker_custom">benutzerdefiniert</string> <string name="custom_time_unit_months">Monate</string> <string name="custom_time_picker_select">Auswählen</string> @@ -1330,7 +1324,7 @@ <string name="share_text_deleted_at">Gelöscht um: %s</string> <string name="info_row_disappears_at">Verschwindet um</string> <string name="share_text_disappears_at">Verschwindet um: %s</string> - <string name="edit_history">Vergangenheit</string> + <string name="edit_history">Nachrichtenverlauf bearbeiten</string> <string name="message_reactions_prohibited_in_this_chat">In diesem Chat sind Reaktionen auf Nachrichten nicht erlaubt.</string> <string name="item_info_no_text">Kein Text</string> <string name="non_fatal_errors_occured_during_import">Während des Imports sind einige nicht schwerwiegende Fehler aufgetreten – weitere Details finden Sie in der Chat-Konsole.</string> @@ -1344,12 +1338,12 @@ <string name="files_and_media">Dateien und Medien</string> <string name="allow_to_send_files">Das Senden von Dateien und Medien erlauben.</string> <string name="prohibit_sending_files">Das Senden von Dateien und Medien nicht erlauben.</string> - <string name="abort_switch_receiving_address">Wechsel der Adresse abbrechen</string> - <string name="abort_switch_receiving_address_question">Wechsel der Adresse abbrechen\?</string> + <string name="abort_switch_receiving_address">Wechsel der Empfängeradresse abbrechen</string> + <string name="abort_switch_receiving_address_question">Wechsel der Empfängeradresse abbrechen?</string> <string name="files_and_media_prohibited">Dateien und Medien sind nicht erlaubt!</string> <string name="only_owners_can_enable_files_and_media">Nur Gruppenbesitzer können Dateien und Medien aktivieren.</string> <string name="group_members_can_send_files">Gruppenmitglieder können Dateien und Medien senden.</string> - <string name="abort_switch_receiving_address_desc">Der Wechsel der Adresse wird abgebrochen. Die bisherige Adresse wird weiter verwendet.</string> + <string name="abort_switch_receiving_address_desc">Der Wechsel der Empfängeradresse wird abgebrochen. Die bisherige Adresse wird weiter verwendet.</string> <string name="files_are_prohibited_in_group">In dieser Gruppe sind Dateien und Medien nicht erlaubt.</string> <string name="unfavorite_chat">Favorit entfernen</string> <string name="favorite_chat">Favorit</string> @@ -1362,7 +1356,7 @@ <string name="error_synchronizing_connection">Fehler beim Synchronisieren der Verbindung</string> <string name="sync_connection_force_question">Verschlüsselung neu aushandeln\?</string> <string name="fix_connection_question">Verbindung reparieren\?</string> - <string name="no_history">Keine Vergangenheit</string> + <string name="no_history">Kein Nachrichtenverlauf</string> <string name="sync_connection_force_confirm">Neu aushandeln</string> <string name="sync_connection_force_desc">Die Verschlüsselung funktioniert und ein neues Verschlüsselungsabkommen ist nicht erforderlich. Es kann zu Verbindungsfehlern kommen!</string> <string name="renegotiate_encryption">Verschlüsselung neu aushandeln</string> @@ -1488,14 +1482,14 @@ <string name="expand_verb">Erweitern</string> <string name="connect_plan_repeat_connection_request">Verbindungsanfrage wiederholen?</string> <string name="rcv_direct_event_contact_deleted">Gelöschter Kontakt</string> - <string name="connect_plan_you_are_already_connecting_to_vName">Sie sind bereits mit %1$s verbunden.</string> + <string name="connect_plan_you_are_already_connecting_to_vName"><![CDATA[Sie sind bereits mit <b>%1$s</b> verbunden.]]></string> <string name="error_alert_title">Fehler</string> <string name="connect_plan_you_are_already_joining_the_group_via_this_link">Sie sind über diesen Link bereits Mitglied der Gruppe.</string> <string name="create_group_button">Gruppe erstellen</string> <string name="create_another_profile_button">Profil erstellen</string> <string name="group_members_2">%s und %s</string> <string name="connect_plan_join_your_group">Ihrer Gruppe beitreten?</string> - <string name="connect_plan_you_are_already_joining_the_group_vName">Sie sind bereits Mitglied in der Gruppe %1$s.</string> + <string name="connect_plan_you_are_already_joining_the_group_vName"><![CDATA[Sie sind bereits Mitglied in der Gruppe <b>%1$s</b>.]]></string> <string name="connect_plan_this_is_your_own_one_time_link">Das ist Ihr eigener Einmal-Link!</string> <string name="marked_deleted_items_description">%d Nachrichten als gelöscht markiert</string> <string name="connect_plan_group_already_exists">Gruppe besteht bereits!</string> @@ -1506,11 +1500,11 @@ <string name="connect_plan_connect_via_link">Über einen Link verbinden?</string> <string name="connect_plan_already_joining_the_group">Sie sind bereits Mitglied der Gruppe!</string> <string name="group_members_n">%s, %s und %d Mitglieder</string> - <string name="moderated_items_description">%d Nachrichten von %s moderiert</string> + <string name="moderated_items_description">%1$d Nachrichten von %2$s moderiert</string> <string name="unblock_member_button">Mitglied freigeben</string> <string name="connect_plan_connect_to_yourself">Mit Ihnen selbst verbinden?</string> - <string name="contact_tap_to_connect">Zum Verbinden antippen</string> - <string name="connect_plan_you_are_already_in_group_vName">Sie sind bereits Mitglied in der Gruppe %1$s.</string> + <string name="contact_tap_to_connect">Zum Verbinden tippen</string> + <string name="connect_plan_you_are_already_in_group_vName"><![CDATA[Sie sind bereits Mitglied in der Gruppe <b>%1$s</b>.]]></string> <string name="connect_plan_this_is_your_own_simplex_address">Das ist Ihre eigene SimpleX-Adresse!</string> <string name="correct_name_to">Richtiger Name für %s?</string> <string name="delete_messages__question">%d Nachrichten löschen?</string> @@ -1518,7 +1512,7 @@ <string name="remove_member_button">Mitglied entfernen</string> <string name="block_member_confirmation">Blockieren</string> <string name="unblock_member_question">Mitglied freigeben?</string> - <string name="blocked_items_description">%d Nachrichten blockiert</string> + <string name="blocked_items_description">%d Nachrichten wurden blockiert</string> <string name="block_member_button">Mitglied blockieren</string> <string name="connect_plan_repeat_join_request">Verbindungsanfrage wiederholen?</string> <string name="button_remove_member_question">Mitglied entfernen?</string> @@ -1531,13 +1525,13 @@ <string name="block_member_question">Mitglied blockieren?</string> <string name="rcv_group_events_count">%d Gruppenereignisse</string> <string name="invalid_name">Ungültiger Name!</string> - <string name="connect_plan_this_is_your_link_for_group_vName">Das ist Ihr Link für die Gruppe %1$s!</string> + <string name="connect_plan_this_is_your_link_for_group_vName"><![CDATA[Das ist Ihr Link für die Gruppe <b>%1$s</b>!]]></string> <string name="unblock_member_confirmation">Freigeben</string> <string name="non_content_uri_alert_title">Ungültiger Datei-Pfad</string> <string name="connect_plan_you_have_already_requested_connection_via_this_address">Sie haben über diese Adresse bereits eine Verbindung beantragt!</string> <string name="terminal_always_visible">Die Konsole in einem neuen Fenster anzeigen</string> - <string name="block_member_desc">Alle neuen Nachrichten von %s werden ausgeblendet!</string> - <string name="blocked_item_description">blockiert</string> + <string name="block_member_desc">Von %s werden alle neuen Nachrichten ausgeblendet!</string> + <string name="blocked_item_description">Blockiert</string> <string name="encryption_renegotiation_error">Fehler bei der Neuverhandlung der Verschlüsselung</string> <string name="alert_text_encryption_renegotiation_failed">Neuverhandlung der Verschlüsselung fehlgeschlagen</string> <string name="v5_4_block_group_members">Gruppenmitglieder blockieren</string> @@ -1579,7 +1573,7 @@ <string name="v5_4_better_groups_descr">Schnellerer Gruppenbeitritt und zuverlässigere Nachrichtenzustellung.</string> <string name="linked_mobiles">Verknüpfte Mobiltelefone</string> <string name="this_device_name">Dieser Gerätename</string> - <string name="waiting_for_mobile_to_connect">Auf die Mobiltelefonverbindung warten:</string> + <string name="waiting_for_mobile_to_connect">Auf die Verbindung des Mobiltelefons warten:</string> <string name="loading_remote_file_title">Laden der Datei</string> <string name="link_a_mobile">Zu einem Mobiltelefon verbinden</string> <string name="settings_section_title_use_from_desktop">Vom Desktop aus nutzen</string> @@ -1603,4 +1597,120 @@ <string name="found_desktop">Gefundener Desktop</string> <string name="not_compatible">Nicht kompatibel!</string> <string name="multicast_discoverable_via_local_network">Über das lokale Netzwerk auffindbar</string> + <string name="refresh_qr_code">Aktualisieren</string> + <string name="create_chat_profile">Chat-Profil erstellen</string> + <string name="disconnect_remote_hosts">Mobiltelefone trennen</string> + <string name="no_connected_mobile">Kein Mobiltelefon verbunden</string> + <string name="random_port">Zufällig</string> + <string name="open_port_in_firewall_desc">Um einer Mobiltelefon-App die Verbindung zum Desktop zu ermöglichen, öffnen Sie diesen Port in Ihrer Firewall, falls Sie diese aktiviert haben</string> + <string name="open_port_in_firewall_title">Port in Firewall öffnen</string> + <string name="app_was_crashed">Ansicht abgestürzt</string> + <string name="error_showing_content">Fehler beim Anzeigen des Inhalts</string> + <string name="error_showing_message">Fehler beim Anzeigen der Nachricht</string> + <string name="you_can_make_address_visible_via_settings">Sie können sie über Einstellungen für Ihre SimpleX-Kontakte sichtbar machen.</string> + <string name="recent_history_is_not_sent_to_new_members">Der Nachrichtenverlauf wird nicht an neue Gruppenmitglieder gesendet.</string> + <string name="retry_verb">Wiederholen</string> + <string name="camera_not_available">Kamera nicht verfügbar</string> + <string name="enable_sending_recent_history">Bis zu 100 der letzten Nachrichten an neue Gruppenmitglieder senden.</string> + <string name="add_contact_button_to_create_link_or_connect_via_link"><![CDATA[<b>Kontakt hinzufügen</b>: Um einen neuen Einladungslink zu erstellen oder eine Verbindung über einen Link herzustellen, den Sie erhalten haben.]]></string> + <string name="disable_sending_recent_history">Den Nachrichtenverlauf nicht an neue Mitglieder senden.</string> + <string name="or_show_this_qr_code">Oder diesen QR-Code anzeigen</string> + <string name="recent_history_is_sent_to_new_members">Bis zu 100 der letzten Nachrichten werden an neue Mitglieder gesendet.</string> + <string name="code_you_scanned_is_not_simplex_link_qr_code">Der von Ihnen gescannte Code ist kein SimpleX-Link-QR-Code.</string> + <string name="the_text_you_pasted_is_not_a_link">Der von Ihnen eingefügte Text ist kein SimpleX-Link.</string> + <string name="enable_camera_access">Kamera-Zugriff aktivieren</string> + <string name="you_can_view_invitation_link_again">Den Einladungslink können Sie in den Details der Verbindung nochmals sehen.</string> + <string name="keep_unused_invitation_question">Nicht genutzte Einladung behalten?</string> + <string name="share_this_1_time_link">Teilen Sie diesen Einmal-Einladungslink</string> + <string name="create_group_button_to_create_new_group"><![CDATA[<b>Gruppe erstellen</b>: Um eine neue Gruppe zu erstellen.]]></string> + <string name="recent_history">Sichtbarer Nachrichtenverlauf</string> + <string name="la_app_passcode">App-Zugangscode</string> + <string name="new_chat">Neuer Chat</string> + <string name="loading_chats">Chats werden geladen…</string> + <string name="creating_link">Link wird erstellt…</string> + <string name="or_scan_qr_code">Oder den QR-Code scannen</string> + <string name="invalid_qr_code">Ungültiger QR-Code</string> + <string name="add_contact_tab">Kontakt hinzufügen</string> + <string name="tap_to_scan">Zum Scannen tippen</string> + <string name="keep_invitation_link">Behalten</string> + <string name="tap_to_paste_link">Zum Link einfügen tippen</string> + <string name="search_or_paste_simplex_link">Suchen oder fügen Sie den SimpleX-Link ein</string> + <string name="chat_is_stopped_you_should_transfer_database">Der Chat wurde gestoppt. Wenn diese Datenbank bereits auf einem anderen Gerät von Ihnen verwendet wurde, sollten Sie diese dorthin zurück übertragen, bevor Sie den Chat starten.</string> + <string name="start_chat_question">Chat starten?</string> + <string name="show_internal_errors">Interne Fehler anzeigen</string> + <string name="remote_ctrl_error_timeout">Während der Verbindung zum Desktop erfolgte eine Zeitüberschreitung</string> + <string name="failed_to_create_user_invalid_title">Ungültiger Anzeigename!</string> + <string name="remote_host_disconnected_from"><![CDATA[Vom Mobiltelefon <b>%s</b> aus folgendem Grund getrennt: %s]]></string> + <string name="remote_host_error_inactive"><![CDATA[Mobiltelefon <b>%s</b> ist nicht aktiv]]></string> + <string name="remote_ctrl_error_bad_state">Die Verbindung zum Desktop ist in einem schlechten Zustand</string> + <string name="remote_host_error_bad_state"><![CDATA[Die Verbindung zum Mobiltelefon <b>%s</b> ist in einem schlechten Zustand]]></string> + <string name="remote_ctrl_error_busy">Desktop ist besetzt</string> + <string name="remote_ctrl_error_inactive">Desktop ist nicht aktiv</string> + <string name="remote_ctrl_error_disconnected">Desktop ist getrennt</string> + <string name="remote_host_error_disconnected"><![CDATA[Mobiltelefon <b>%s</b> wurde getrennt]]></string> + <string name="remote_ctrl_error_bad_version">Auf dem Desktop wird eine nicht unterstützte Version verwendet. Bitte stellen Sie sicher, dass beide Geräte die selbe Version nutzen</string> + <string name="remote_ctrl_error_bad_invitation">Desktop hat einen falschen Einladungscode</string> + <string name="agent_critical_error_title">Kritischer Fehler</string> + <string name="remote_host_error_missing"><![CDATA[Mobiltelefon <b>%s</b> ist nicht vorhanden]]></string> + <string name="agent_internal_error_desc">Bitte melden Sie diesen Fehler den Entwicklern: +\n%s</string> + <string name="agent_critical_error_desc">Bitte melden Sie diesen Fehler den Entwicklern: +\n%s +\n +\nEs wird empfohlen die App neu zu starten.</string> + <string name="restart_chat_button">Chat neu starten</string> + <string name="failed_to_create_user_invalid_desc">Der Anzeigename ist ungültig. Bitte wählen Sie einen anderen Namen.</string> + <string name="remote_host_error_timeout"><![CDATA[Während der Verbindung zum Mobiltelefon <b>%s</b> erfolgte eine Zeitüberschreitung]]></string> + <string name="remote_host_was_disconnected_title">Verbindung wurde getrennt</string> + <string name="remote_ctrl_was_disconnected_title">Verbindung wurde getrennt</string> + <string name="remote_ctrl_disconnected_with_reason">Aus folgendem Grund getrennt: %s</string> + <string name="agent_internal_error_title">Interner Fehler</string> + <string name="remote_host_error_bad_version"><![CDATA[Auf dem Mobiltelefon <b>%s</b> wird eine nicht unterstützte Version verwendet. Bitte stellen Sie sicher, dass beide Geräte die selbe Version nutzen]]></string> + <string name="remote_host_error_busy"><![CDATA[Mobiltelefon <b>%s</b> ist besetzt]]></string> + <string name="past_member_vName">Ehemaliges Mitglied %1$s</string> + <string name="possible_slow_function_desc">Die Ausführung dieser Funktion dauert zu lange: %1$d Sekunden: %2$s</string> + <string name="possible_slow_function_title">Langsame Funktion</string> + <string name="show_slow_api_calls">Zeige langsame API-Aufrufe an</string> + <string name="group_member_status_unknown_short">unbekannt</string> + <string name="possible_deadlock_title">Blockade</string> + <string name="developer_options_section">Optionen für Entwickler</string> + <string name="possible_deadlock_desc">Die Code-Ausführung dauert zu lange: %1$d Sekunden. Wahrscheinlich ist die App eingefroren: %2$s</string> + <string name="group_member_status_unknown">unbekannter Gruppenmitglieds-Status</string> + <string name="v5_5_private_notes_descr">Mit verschlüsselten Dateien und Medien.</string> + <string name="v5_5_private_notes">Private Notizen</string> + <string name="clear_note_folder_warning">Es werden alle Nachrichten gelöscht. Dieser Vorgang kann nicht rückgängig gemacht werden!</string> + <string name="clear_note_folder_question">Private Notizen löschen?</string> + <string name="rcv_group_event_member_blocked">%s wurde blockiert</string> + <string name="rcv_group_event_member_unblocked">%s wurde freigegeben</string> + <string name="snd_group_event_member_blocked">Sie haben %s blockiert</string> + <string name="snd_group_event_member_unblocked">Sie haben %s freigegeben</string> + <string name="block_for_all_question">Mitglied für Alle blockieren?</string> + <string name="saved_message_title">Gespeicherte Nachricht</string> + <string name="v5_5_simpler_connect_ui">Zum Verbinden den Link einfügen!</string> + <string name="v5_5_message_delivery_descr">Mit reduziertem Akkuverbrauch.</string> + <string name="v5_5_join_group_conversation_descr">Aktueller Nachrichtenverlauf und verbesserter Gruppenverzeichnis-Bot.</string> + <string name="v5_5_simpler_connect_ui_descr">Von der Suchleiste werden Einladungslinks akzeptiert.</string> + <string name="unblock_for_all">Für Alle freigeben</string> + <string name="unblock_for_all_question">Mitglied für Alle freigeben?</string> + <string name="member_info_member_blocked">wurde blockiert</string> + <string name="blocked_by_admin_item_description">ist vom Administrator blockiert worden</string> + <string name="member_blocked_by_admin">wurde vom Administrator blockiert</string> + <string name="block_for_all">Für Alle blockiert</string> + <string name="info_row_created_at">Erstellt um</string> + <string name="share_text_created_at">Erstellt um: %s</string> + <string name="blocked_by_admin_items_description">%d Nachrichten wurden vom Administrator blockiert</string> + <string name="error_blocking_member_for_all">Fehler beim Blockieren des Mitglieds für Alle</string> + <string name="error_creating_message">Fehler beim Erstellen der Nachricht</string> + <string name="error_deleting_note_folder">Fehler beim Löschen der privaten Notizen</string> + <string name="v5_5_message_delivery">Verbesserte Zustellung von Nachrichten</string> + <string name="v5_5_join_group_conversation">Gruppenunterhaltungen beitreten</string> + <string name="v5_5_new_interface_languages">Ungarische und türkische Bedienoberfläche</string> + <string name="profile_update_event_contact_name_changed">Kontaktname %1$s wurde auf %2$s geändert</string> + <string name="profile_update_event_member_name_changed">Mitgliedsname %1$s wurde auf %2$s geändert</string> + <string name="profile_update_event_set_new_address">Neue Kontaktadresse wurde festgelegt</string> + <string name="profile_update_event_set_new_picture">Neues Profil-Bild wurde festgelegt</string> + <string name="profile_update_event_updated_profile">Das Profil wurde aktualisiert</string> + <string name="profile_update_event_removed_picture">Profil-Bild wurde entfernt</string> + <string name="profile_update_event_removed_address">Kontaktadresse wurde entfernt</string> + <string name="note_folder_local_display_name">Private Notizen</string> </resources> \ No newline at end of file diff --git a/apps/multiplatform/common/src/commonMain/resources/MR/el/strings.xml b/apps/multiplatform/common/src/commonMain/resources/MR/el/strings.xml index 7063eb9007..811257ff39 100644 --- a/apps/multiplatform/common/src/commonMain/resources/MR/el/strings.xml +++ b/apps/multiplatform/common/src/commonMain/resources/MR/el/strings.xml @@ -56,4 +56,175 @@ <string name="always_use_relay">Να χρησιμοποιείται πάντα αναμεταδότη</string> <string name="search_verb">Αναζήτηση</string> <string name="la_mode_off">Ανενεργό</string> + <string name="connect__your_profile_will_be_shared">"Το προφίλ σας %1$s θα μοιραστεί"</string> + <string name="your_simplex_contact_address">Η SimpleX διεύθυνση σας</string> + <string name="full_backup">Αντίγραφο δεδομένων εφαρμογής</string> + <string name="send_disappearing_message_5_minutes">5 λεπτά</string> + <string name="you_will_be_connected_when_your_contacts_device_is_online">Θα συνδεθείτε όταν η συσκευή της επαφής σας είναι συνδεμένει, παρακαλώ περιμένετε ή ελέγξτε αργότερα!</string> + <string name="your_ice_servers">Ο ICE διακομιστής σας</string> + <string name="app_version_title">Έκδοση εφαρμογής</string> + <string name="you_sent_group_invitation">Στείλατε πρόσκληση ομάδας</string> + <string name="send_disappearing_message_1_minute">1 λεπτό</string> + <string name="smp_servers_your_server">Ο διακομιστής σας</string> + <string name="address_section_title">Διεύθυνση</string> + <string name="abort_switch_receiving_address_confirm">Ακύρωση</string> + <string name="back">Πίσω</string> + <string name="send_disappearing_message_30_seconds">30 δευτερόλεπτα</string> + <string name="you_will_join_group">Θα συνδεθείτε με όλα τα μέλη της ομάδας.</string> + <string name="contact_wants_to_connect_via_call">%1$s θέλει να συνδεθεί μαζί σου μέσω</string> + <string name="allow_message_reactions">Επιτρέπονται αντιδράσεις μηνύματος.</string> + <string name="your_XFTP_servers">Ο διακομιστής XFTP σας</string> + <string name="smp_servers_your_server_address">Η διεύθυνση του διακομιστή σας</string> + <string name="your_profile_is_stored_on_your_device">Το προφίλ, επαφές και παραδομένα μηνύματα σας είναι αποθηκευμένα στην συσκευή σας.</string> + <string name="your_SMP_servers">Ο διακομιστής SMP σας</string> + <string name="allow_to_send_files">Επιτρέπεται να σταλούν αρχεία και μέσα.</string> + <string name="incognito_random_profile">Το τυχαίο προφίλ σας</string> + <string name="group_info_section_title_num_members">%1$s ΜΕΛΗ</string> + <string name="turn_off_battery_optimization_button">Επιτρέπεται</string> + <string name="your_preferences">Οι προτιμήσεις σας</string> + <string name="group_member_role_author">Συντάκτης</string> + <string name="your_ICE_servers">Ο ΙCE διακομιστής σας</string> + <string name="v5_0_app_passcode">Κωδικός εφαρμογής</string> + <string name="connect_via_member_address_alert_desc">Αίτημα σύνδεσης θα σταλεί σε αυτό το μέλος της ομάδας.</string> + <string name="settings_section_title_icon">ΟΙΚΟΝΑ ΕΦΑΡΜΟΓΗΣ</string> + <string name="settings_section_title_app">Εφαρμογή</string> + <string name="your_settings">Οι ρυθμίσεις σας</string> + <string name="app_version_name">Έκδοση εφαρμογής: v%s</string> + <string name="callstatus_error">σφάλμα κλήσης</string> + <string name="feature_cancelled_item">"ακυρώθηκε %s"</string> + <string name="icon_descr_cancel_link_preview">ακύρωση πρόβλεψη συνδέσμου</string> + <string name="change_database_passphrase_question">Αλλαγή κωδικού πρόσβασης βάση δεδομένων?</string> + <string name="la_change_app_passcode">Αλλαγή κωδικού πρόσβασης</string> + <string name="rcv_group_event_changed_member_role">Αλλαγή ρόλου του %s σε %s</string> + <string name="color_background">Φόντο</string> + <string name="database_initialization_error_title">Δεν είναι δυνατή η προετοιμασία της βάσης δεδομένων</string> + <string name="connect__a_new_random_profile_will_be_shared">Ένα νέο τυχαίο προφίλ θα μοιραστεί.</string> + <string name="alert_title_cant_invite_contacts">Δεν είναι δυνατή η πρόσκληση επαφών!</string> + <string name="chat_archive_header">Αρχείο συνομιλίας</string> + <string name="switch_receiving_address">Αλλαγή διεύθυνσης λήψης</string> + <string name="auth_unavailable">Πιστοποίηση μη διαθέσιμη</string> + <string name="change_verb">Αλλαγή</string> + <string name="available_in_v51">" +\nΔιαθέσιμο στην έκδοση 5.1"</string> + <string name="icon_descr_call_ended">Τέλος κλήσης</string> + <string name="settings_section_title_calls">ΚΛΗΣΕΙΣ</string> + <string name="auto_accept_contact">Αυτόματη αποδοχή</string> + <string name="alert_text_decryption_error_n_messages_failed_to_decrypt">%1$d αποτυχία κρυπτογράφησης μηνύματος</string> + <string name="snd_conn_event_switch_queue_phase_changing_for_member">αλλαγή διεύθυνσης για %s…</string> + <string name="change_member_role_question">Αλλαγή ρόλου ομάδας;</string> + <string name="chat_archive_section">ΑΡΧΕΙΟ ΣΥΝΟΜΙΛΙΑΣ</string> + <string name="invite_prohibited">Δεν είναι δυνατή η πρόσκληση επαφής!</string> + <string name="v4_2_auto_accept_contact_requests">Αυτόματη αποδοχή αιτήματος επαφής</string> + <string name="callstatus_calling">Κλήση…</string> + <string name="icon_descr_cancel_file_preview">Ακύρωση πρόβλεψη αρχείου</string> + <string name="block_member_confirmation">Φραγή</string> + <string name="icon_descr_cancel_image_preview">Ακύρωση πρόβλεψη εικόνας</string> + <string name="snd_conn_event_switch_queue_phase_changing">αλλαγή διεύθυνσης…</string> + <string name="v5_2_more_things">Μερικά παραπάνω πράγματα</string> + <string name="authentication_cancelled">Πιστοποίηση ακυρώθηκε</string> + <string name="change_self_destruct_passcode">Αλλαγή κωδικού αυτοκαταστροφής</string> + <string name="change_role">Αλλαγή ρολου</string> + <string name="icon_descr_cancel_live_message">Ακύρωση ζωντανών μυνημάτων</string> + <string name="all_app_data_will_be_cleared">Όλα τα δεδομένα της εφαρμογής διαγράφηκαν.</string> + <string name="appearance_settings">Εμφάνιση</string> + <string name="callstatus_ended">Τέλος κλήσης %1$s</string> + <string name="cancel_verb">Ακύρωση</string> + <string name="switch_receiving_address_question">Αλλαγή διεύθυνσης λήψης;</string> + <string name="rcv_conn_event_switch_queue_phase_changing">αλλαγή διεύθυνσης…</string> + <string name="change_self_destruct_mode">Αλλαγή λειτουργίας αυτοκαταστροφής</string> + <string name="use_camera_button">Κάμερα</string> + <string name="callstatus_in_progress">κλήση σε εξέλιξη</string> + <string name="auto_accept_images">Αυτόματη αποδοχή εικόνων</string> + <string name="rcv_group_event_changed_your_role">Αλλαγή του ρόλου σας σε %s</string> + <string name="icon_descr_call_progress">Κλήση σε εξέλιξη</string> + <string name="la_auth_failed">Πιστοποίηση απέτυχε</string> + <string name="connection_local_display_name">"σύνδεση %1$d"</string> + <string name="create_simplex_address">Δημιουργία διεύθυνση SimpleX</string> + <string name="status_contact_has_e2e_encryption">επαφή έχει κρυπτογράφηση από άκρο σε άκρο</string> + <string name="v5_4_incognito_groups_descr">Δημιουργία μια ομάδας χρησιμοποιώντας ένα τυχαίο προφίλ.</string> + <string name="create_group_button">Δημιουργία ομάδας</string> + <string name="create_another_profile_button">Δημιουργία προφίλ</string> + <string name="delete_contact_all_messages_deleted_cannot_undo_warning">Η επαφή και όλα τα μηνύματα θα διαγραφούν - αυτό δεν μπορεί να αναιρεθεί!</string> + <string name="create_profile">Δημιουργία προφίλ</string> + <string name="contacts_can_mark_messages_for_deletion">Οι επαφές μπορούν να επισημάνουν μηνύματα προς διαγραφή; θα μπορείτε να τα δείτε.</string> + <string name="connect_via_invitation_link">Σύνδεση μέσω μιας εφάπαξ σύνδεσης;</string> + <string name="button_create_group_link">Δημιουργία σύνδεσμου</string> + <string name="connect_via_link_or_qr">Σύνδεση μέσω σύνδεσμο/κωδικό γρήγορης ανταπόκρισης</string> + <string name="connection_error_auth">Σφάλμα σύνδεσης (πιστοποίηση)</string> + <string name="group_member_status_connecting">συνδέεται</string> + <string name="group_connection_pending">συνδέεται…</string> + <string name="notification_preview_mode_contact">Όνομα επαφής</string> + <string name="create_address">Δημιουργία διεύθυνσης</string> + <string name="copy_verb">Αντιγραφή</string> + <string name="continue_to_next_step">Συνέχεια</string> + <string name="connect_plan_connect_via_link">Σύνδεση μέσω σύνδεσμο;</string> + <string name="contact_already_exists">Επαφή υπάρχει ήδη</string> + <string name="connect_plan_connect_to_yourself">Σύνδεση στον εαυτό σας;</string> + <string name="create_group">Δημιουργία μυστικής ομάδας</string> + <string name="connected_to_desktop">Συνδεδεμένη σε επιφάνεια εργασίας</string> + <string name="group_member_status_creator">δημιουργός</string> + <string name="connection_request_sent">Αίτημα σύνδεσης στάλθηκε!</string> + <string name="connecting_to_desktop">Συνδεμένο σε επιφάνεια εργασίας</string> + <string name="network_session_mode_entity">Σύνδεση</string> + <string name="correct_name_to">Διόρθωση ονόματος σε %s;</string> + <string name="connection_timeout">Λήξη χρονικού ορίου σύνδεσης</string> + <string name="group_member_status_accepted">σύνδεση (αποδεκτή)</string> + <string name="connect_with_contact_name_question">Σύνδεση με %1$s?</string> + <string name="create_your_profile">Δημιουργία του προφίλ σου</string> + <string name="display_name_connecting">συνδέεται…</string> + <string name="create_profile_button">Δημιουργία</string> + <string name="contact_preferences">Προτιμήσεις επαφής</string> + <string name="connected_mobile">Συνδεδεμένο κινητό</string> + <string name="info_row_connection">Σύνδεση</string> + <string name="create_chat_profile">Δημιουργία προφίλ συνομιλίας</string> + <string name="callstate_connecting">συνδέεται…</string> + <string name="desktop_connection_terminated">Σύνδεση τερματίστηκε</string> + <string name="server_connecting">Συνδε</string> + <string name="connect_via_link_incognito">Σύνδεση ανώνυμης περιήγησης</string> + <string name="display_name_connection_established">σύνδεση επετεύχθη</string> + <string name="status_contact_has_no_e2e_encryption">επαφή δεν έχει κρυπτογράφηση από άκρο σε άκρο</string> + <string name="chat_preferences_contact_allows">Επαφή επιτρέπει</string> + <string name="group_member_status_announced">σύνδεση (ανακοινώθηκε)</string> + <string name="icon_descr_server_status_connected">Συνδεδεμένος</string> + <string name="contact_connection_pending">συνδέεται…</string> + <string name="create_group_link">Δημιουργία σύνδεσμο ομάδας</string> + <string name="connect_to_desktop">Σύνδεση σε επιφάνεια εργασίας</string> + <string name="archive_created_on_ts">Δημιουργήθηκε στις %1$s</string> + <string name="connected_to_mobile">Συνδεδεμένο στο κινητό</string> + <string name="connect_via_link">Σύνδεση μέσω σύνδεσμο</string> + <string name="receipts_section_contacts">Επαφές</string> + <string name="smp_server_test_create_file">Δημιουργία αρχείου</string> + <string name="create_secret_group_title">Δημιουργία μυστικής ομάδας</string> + <string name="connection_error">Σφάλμα σύνδεσης</string> + <string name="alert_title_contact_connection_pending">Η επαφή δεν είναι συνδράμει αυτή τη στιγμή!</string> + <string name="rcv_group_event_member_created_contact">Συνδεδεμένο απευθείας</string> + <string name="your_privacy">Η ιδιωτικότητά σας</string> + <string name="contact_sent_large_file">Η επαφή σας έστειλε ένα αρχείο το οποίο είναι μεγαλύτερο από το παρόν υποστηριζόμενο μέγεθος (%1$s).</string> + <string name="your_chat_profile_will_be_sent_to_your_contact">Το προφίλ της συνομιλίας σας θα σταλεί στην επαφή σας</string> + <string name="connect_use_new_incognito_profile">Χρήση νέου ανώνυμου προφίλ</string> + <string name="connect_plan_already_connecting">Ήδη συνδέεται</string> + <string name="you_rejected_group_invitation">Απορρίψατε την πρόσκληση της ομάδας</string> + <string name="connect_via_contact_link">Σύνδεση μέσω διεύθυνση επαφής</string> + <string name="connect_use_current_profile">Χρήση του τρέχων προφίλ</string> + <string name="connect_via_link_verb">Σύνδεση</string> + <string name="your_current_profile">Το τρέχον προφίλ σας</string> + <string name="snd_group_event_member_deleted">αφαιρέσατε %1$s</string> + <string name="connect_via_group_link">"Συμμετοχή ομάδας;"</string> + <string name="your_contacts_will_remain_connected">Οι επαφες σας θα παραμένουν συνδεδεμένες.</string> + <string name="trying_to_connect_to_server_to_receive_messages">Προσπάθεια σύνδεσης με τον διακομιστή που χρησιμοποιείται για τη λήψη μηνυμάτων από αυτήν την επαφή.</string> + <string name="profile_will_be_sent_to_contact_sending_link">Το προφίλ σου θα σταλεί στην επαφή από την οποία έλαβες αυτόν τον σύνδεσμο.</string> + <string name="server_error">σφάλμα</string> + <string name="opening_database">Άνοιγμα βάση δεδομένων…</string> + <string name="app_was_crashed">Η προβολή συνετρίβη</string> + <string name="server_connected">συνδεδεμένο</string> + <string name="non_content_uri_alert_text">Κοινοποιήσατε μια μη έγκυρη διαδρομή αρχείου. Αναφέρετε το πρόβλημα στους προγραμματιστές της εφαρμογής.</string> + <string name="non_content_uri_alert_title">Μη έγκυρη διαδρομή αρχείου</string> + <string name="connected_to_server_to_receive_messages_from_contact">Είστε συνδεδεμένοι στον διακομιστή που χρησιμοποιείται για τη λήψη μηνυμάτων από αυτήν την επαφή.</string> + <string name="marked_deleted_items_description">%d μύνημα επισημάνθηκε ως διαγραμμένο</string> + <string name="moderated_items_description">%1$d μυνήματα συντονίζονται από %2$s</string> + <string name="marked_deleted_description">επισημάνθηκε ως διαγραμμένο</string> + <string name="blocked_items_description">%d μυνήματα φραγμένα</string> + <string name="deleted_description">διαγράφτηκε</string> + <string name="moderated_item_description">με συντονιστή %s</string> + <string name="blocked_item_description">φραγμένος</string> </resources> \ No newline at end of file diff --git a/apps/multiplatform/common/src/commonMain/resources/MR/es/strings.xml b/apps/multiplatform/common/src/commonMain/resources/MR/es/strings.xml index 246ed36859..f67a753bb5 100644 --- a/apps/multiplatform/common/src/commonMain/resources/MR/es/strings.xml +++ b/apps/multiplatform/common/src/commonMain/resources/MR/es/strings.xml @@ -3,8 +3,8 @@ <string name="auth_unavailable">Autenticación no disponible</string> <string name="accept_contact_button">Aceptar</string> <string name="network_settings">Configuración avanzada de red</string> - <string name="onboarding_notifications_mode_off_desc"><![CDATA[<b>Mejor para la batería</b>. Recibirás notificaciones sólo cuando la aplicación se esté ejecutando, SIN servicio en segundo plano.]]></string> - <string name="onboarding_notifications_mode_periodic_desc"><![CDATA[<b>Bueno para la batería</b>. El servicio en segundo plano comprueba si hay mensajes cada 10 minutos. Puedes perder llamadas o mensajes urgentes.]]></string> + <string name="onboarding_notifications_mode_off_desc"><![CDATA[<b>Óptimo para la batería</b>. Recibirás notificaciones sólo cuando la aplicación esté abierta (SIN servicio en segundo plano).]]></string> + <string name="onboarding_notifications_mode_periodic_desc"><![CDATA[<b>Bueno para la batería</b>. El servicio en segundo plano comprueba si hay mensajes cada 10 minutos. Podrías no recibir a tiempo llamadas o mensajes urgentes.]]></string> <string name="accept_call_on_lock_screen">Aceptar</string> <string name="full_backup">Copia de seguridad de los datos de la aplicación</string> <string name="chat_item_ttl_day">un dia</string> @@ -14,7 +14,7 @@ <string name="v4_3_improved_server_configuration_desc">Añadir servidores mediante el escaneo de códigos QR.</string> <string name="smp_servers_preset_add">Añadir servidores predefinidos</string> <string name="all_group_members_will_remain_connected">Todos los miembros del grupo permanecerán conectados.</string> - <string name="allow_irreversible_message_deletion_only_if">Se permite la eliminación irreversible de mensajes pero sólo si tu contacto también lo permite para tí.</string> + <string name="allow_irreversible_message_deletion_only_if">Se permite la eliminación irreversible de mensajes pero sólo si tu contacto también lo permite para tí. (24 horas)</string> <string name="keychain_allows_to_receive_ntfs">Android Keystore se usará para almacenar de forma segura la contraseña después de reiniciar la aplicación o cambiar la frase de contraseña - permitirá recibir notificaciones.</string> <string name="allow_your_contacts_to_send_disappearing_messages">Permites a tus contactos enviar mensajes temporales</string> <string name="allow_your_contacts_to_send_voice_messages">Permites a tus contactos enviar mensajes de voz.</string> @@ -27,7 +27,6 @@ <string name="notifications_mode_service">Siempre activo</string> <string name="allow_verb">Permitir</string> <string name="above_then_preposition_continuation">y después:</string> - <string name="add_new_contact_to_create_one_time_QR_code"><![CDATA[<b>Añadir nuevo contacto</b>: para crear tu código QR de un solo uso para tu contacto.]]></string> <string name="accept_connection_request__question">¿Aceptar solicitud de conexión\?</string> <string name="accept_contact_incognito_button">Aceptar incógnito</string> <string name="clear_chat_warning">Se eliminarán todos los mensajes SOLO para tí. ¡No podrá deshacerse!</string> @@ -57,10 +56,10 @@ <string name="keychain_is_storing_securely">Android Keystore se usará para almacenar de forma segura la contraseña - permite que el servicio de notificación funcione.</string> <string name="users_add">Añadir perfil</string> <string name="color_primary">Color</string> - <string name="allow_your_contacts_irreversibly_delete">Permites a tus contactos eliminar irreversiblemente los mensajes enviados.</string> + <string name="allow_your_contacts_irreversibly_delete">Permites a tus contactos eliminar irreversiblemente los mensajes enviados. (24 horas)</string> <string name="allow_voice_messages_only_if">Se permiten los mensajes de voz pero sólo si tu contacto también los permite.</string> <string name="allow_direct_messages">Se permiten mensajes directos entre miembros.</string> - <string name="allow_to_delete_messages">Se permite la eliminación irreversible de mensajes.</string> + <string name="allow_to_delete_messages">Se permite la eliminación irreversible de mensajes. (24 horas)</string> <string name="allow_to_send_voice">Se permiten mensajes de voz.</string> <string name="v4_2_group_links_desc">Los administradores pueden crear enlaces para unirse a grupos.</string> <string name="v4_2_auto_accept_contact_requests">Auto aceptar solicitudes de contacto</string> @@ -76,12 +75,10 @@ <string name="icon_descr_asked_to_receive">Solicita recibir la imagen</string> <string name="impossible_to_recover_passphrase"><![CDATA[<b>Atención</b>: NO podrás recuperar o cambiar la contraseña si la pierdes.]]></string> <string name="both_you_and_your_contact_can_send_voice">Tanto tú como tu contacto podéis enviar mensajes de voz.</string> - <string name="onboarding_notifications_mode_service_desc"><![CDATA[<b>¡Consume más batería!</b> El servicio en segundo plano se ejecuta siempre y las notificaciones se mostrarán en cuanto haya mensajes disponibles.]]></string> - <string name="both_you_and_your_contacts_can_delete">Tanto tú como tu contacto podéis eliminar de forma irreversible los mensajes enviados.</string> + <string name="onboarding_notifications_mode_service_desc"><![CDATA[<b>¡Consume más batería!</b> El servicio en segundo plano se ejecuta continuamente y las notificaciones se mostrarán de inmediato.]]></string> + <string name="both_you_and_your_contacts_can_delete">Tanto tú como tu contacto podéis eliminar los mensajes enviados de forma irreversible. (24 horas)</string> <string name="both_you_and_your_contact_can_send_disappearing">Tanto tú como tu contacto podéis enviar mensajes temporales.</string> - <string name="scan_QR_code_to_connect_to_contact_who_shows_QR_code"><![CDATA[<b>Escanear código QR</b>: para conectar con tu contacto mediante su código QR.]]></string> <string name="create_profile_button">Crear</string> - <string name="create_one_time_link">Crea enlace de invitación de un uso</string> <string name="create_group">Crea grupo secreto</string> <string name="database_passphrase_will_be_updated">La contraseña de cifrado de la base de datos será actualizada.</string> <string name="info_row_database_id">ID base de datos</string> @@ -162,11 +159,11 @@ <string name="icon_descr_server_status_connected">Conectado</string> <string name="copied">Copiado en portapapeles</string> <string name="share_one_time_link">Crea enlace de invitación de un uso.</string> - <string name="desktop_scan_QR_code_from_app_via_scan_QR_code"><![CDATA[💻 PC: escanéa el código QR desde la aplicación mediante <b>Escanear código QR </b>]]></string> + <string name="desktop_scan_QR_code_from_app_via_scan_QR_code"><![CDATA[💻 Ordenador: escanéa el código QR desde la aplicación mediante <b>Escanear código QR </b>]]></string> <string name="delete_contact_menu_action">Eliminar</string> <string name="delete_group_menu_action">Eliminar</string> <string name="alert_title_contact_connection_pending">¡El contacto aun no se ha conectado!</string> - <string name="delete_pending_connection__question">¿Eliminar la conexion pendiente\?</string> + <string name="delete_pending_connection__question">¿Eliminar conexión pendiente?</string> <string name="icon_descr_close_button">Botón cerrar</string> <string name="connection_request_sent">¡Solicitud de conexión enviada!</string> <string name="network_session_mode_entity">por conexión</string> @@ -184,13 +181,13 @@ <string name="notification_preview_somebody">Contacto oculto:</string> <string name="delete_verb">Eliminar</string> <string name="edit_verb">Editar</string> - <string name="delete_member_message__question">¿Eliminar el mensaje de miembro\?</string> + <string name="delete_member_message__question">¿Eliminar el mensaje del miembro?</string> <string name="icon_descr_edited">editado</string> <string name="image_decoding_exception_title">Error de decodificación</string> <string name="create_address">Crear dirección</string> <string name="delete_address">Eliminar dirección</string> <string name="delete_address__question">¿Eliminar la dirección\?</string> - <string name="display_name__field">Nombre mostrado:</string> + <string name="display_name__field">Nombre del perfil:</string> <string name="callstate_connecting">conectando…</string> <string name="decentralized">Descentralizada</string> <string name="database_will_be_encrypted">La base de datos será cifrada.</string> @@ -230,7 +227,7 @@ <string name="ttl_w">%ds</string> <string name="deleted_description">eliminado</string> <string name="connect_via_contact_link">¿Conectar mediante dirección de contacto?</string> - <string name="connect_via_group_link">¿Unirse al grupo?</string> + <string name="connect_via_group_link">¿Unirte al grupo?</string> <string name="connect_via_invitation_link">¿Conectar mediante enlace de invitación?</string> <string name="connect_via_link_verb">Conectar</string> <string name="server_connected">conectado</string> @@ -255,7 +252,7 @@ <string name="change_verb">Cambiar</string> <string name="notifications_mode_periodic_desc">Se realizan comprobaciones de mensajes nuevos periódicas de hasta un minuto de duración cada 10 minutos</string> <string name="clear_contacts_selection_button">Limpiar</string> - <string name="change_member_role_question">¿Cambiar rol de grupo\?</string> + <string name="change_member_role_question">¿Cambiar rol?</string> <string name="v4_4_verify_connection_security_desc">Compara los códigos de seguridad con tus contactos</string> <string name="choose_file">Archivo</string> <string name="clear_verb">Vaciar</string> @@ -267,7 +264,7 @@ <string name="callstatus_in_progress">llamada en curso</string> <string name="colored_text">coloreado</string> <string name="rcv_group_event_changed_your_role">ha cambiado tu rol a %s</string> - <string name="snd_conn_event_switch_queue_phase_changing_for_member">cambiando de servidor para %s</string> + <string name="snd_conn_event_switch_queue_phase_changing_for_member">cambiando el servidor para %s</string> <string name="group_member_status_complete">completado</string> <string name="invite_prohibited">¡No se puede invitar el contacto!</string> <string name="cannot_receive_file">No se puede recibir el archivo</string> @@ -284,7 +281,7 @@ <string name="chat_is_stopped">Chat está detenido</string> <string name="settings_section_title_calls">LLAMADAS</string> <string name="chat_is_running">Chat está en ejecución</string> - <string name="rcv_conn_event_switch_queue_phase_changing">cambiando de servidor…</string> + <string name="rcv_conn_event_switch_queue_phase_changing">está cambiando de servidor…</string> <string name="chat_with_developers">habla con los desarrolladores</string> <string name="icon_descr_cancel_file_preview">Cancelar vista previa del archivo</string> <string name="icon_descr_cancel_image_preview">Cancelar vista previa de la imagen</string> @@ -300,10 +297,10 @@ <string name="clear_chat_menu_action">Vaciar</string> <string name="app_version_code">Build de la aplicación: %s</string> <string name="call_already_ended">¡La llamada ha terminado!</string> - <string name="rcv_conn_event_switch_queue_phase_completed">el servidor de envío ha cambiado para tí</string> + <string name="rcv_conn_event_switch_queue_phase_completed">ha cambiado tu servidor de envío</string> <string name="icon_descr_cancel_link_preview">cancelar vista previa del enlace</string> <string name="call_on_lock_screen">Llamadas en la ventana de bloqueo</string> - <string name="alert_title_cant_invite_contacts">¡No se puede invitar a los contactos!</string> + <string name="alert_title_cant_invite_contacts">¡No se pueden invitar contactos!</string> <string name="chat_console">Consola de Chat</string> <string name="chat_database_section">BASE DE DATOS DE CHAT</string> <string name="chat_database_deleted">Base de datos eliminada</string> @@ -314,7 +311,7 @@ <string name="image_saved">Imagen guardada en la Galería</string> <string name="file_will_be_received_when_contact_is_online">El archivo se recibirá cuando tu contacto esté en línea, por favor espera o compruébalo más tarde.</string> <string name="add_contact">Enlace de invitación de un uso</string> - <string name="paste_the_link_you_received">Pegar enlace recibido</string> + <string name="paste_the_link_you_received">Pegar el enlace recibido</string> <string name="error_saving_group_profile">Error al guardar perfil de grupo</string> <string name="exit_without_saving">Salir sin guardar</string> <string name="file_saved">Archivo guardado</string> @@ -372,7 +369,7 @@ <string name="failed_to_parse_chats_title">No se pudieron cargar los chats</string> <string name="simplex_link_mode_full">Enlace completo</string> <string name="error_deleting_contact">Error al eliminar contacto</string> - <string name="error_joining_group">Error al unirse al grupo</string> + <string name="error_joining_group">Error al unirte al grupo</string> <string name="error_receiving_file">Error al recibir archivo</string> <string name="please_check_correct_link_and_maybe_ask_for_a_new_one">Comprueba que has usado el enlace correcto o pide a tu contacto que te envíe otro.</string> <string name="error_deleting_contact_request">Error al eliminar solicitud del contacto</string> @@ -413,10 +410,10 @@ <string name="section_title_for_console">PARA CONSOLA</string> <string name="error_changing_role">Error al cambiar rol</string> <string name="conn_stats_section_title_servers">SERVIDORES</string> - <string name="group_display_name_field">Introduce un nombre para el grupo:</string> - <string name="group_preferences">Preferencias de grupo</string> + <string name="group_display_name_field">Nombre del grupo:</string> + <string name="group_preferences">Preferencias del grupo</string> <string name="group_members_can_send_dms">Los miembros del grupo pueden enviar mensajes directos.</string> - <string name="group_members_can_delete">Los miembros del grupo pueden eliminar mensajes de forma irreversible.</string> + <string name="group_members_can_delete">Los miembros del grupo pueden eliminar mensajes de forma irreversible. (24 horas)</string> <string name="v4_3_improved_privacy_and_security_desc">Ocultar pantalla de aplicaciones en aplicaciones recientes.</string> <string name="encrypt_database">Cifrar</string> <string name="icon_descr_expand_role">Ampliar la selección de roles</string> @@ -445,17 +442,17 @@ <string name="rcv_group_event_member_added">ha invitado a %1$s</string> <string name="incognito_info_allows">Permite tener varias conexiones anónimas sin datos compartidos entre estas dentro del mismo perfil.</string> <string name="invite_to_group_button">Invitar al grupo</string> - <string name="to_verify_compare">Para comprobar el cifrado de extremo a extremo con tu contacto compara (o escanea) el código en tus dispositivos.</string> + <string name="to_verify_compare">Para verificar el cifrado de extremo a extremo con tu contacto, compara (o escanea) el código en ambos dispositivos.</string> <string name="database_is_not_encrypted">La base de datos no está cifrada. Escribe una contraseña para protegerla.</string> <string name="ensure_smp_server_address_are_correct_format_and_unique">Asegúrate de que las direcciones del servidor SMP tienen el formato correcto, están separadas por líneas y no están duplicadas.</string> <string name="icon_descr_instant_notifications">Notificación instantánea</string> <string name="network_settings_title">Configuración de red</string> <string name="network_use_onion_hosts_no_desc_in_alert">No se usarán hosts .onion</string> <string name="only_client_devices_store_contacts_groups_e2e_encrypted_messages"><![CDATA[Sólo los dispositivos cliente almacenan perfiles de usuario, contactos, grupos y mensajes enviados con <b>cifrado de extremo a extremo de 2 capas</b> .]]></string> - <string name="onboarding_notifications_mode_subtitle">Puede cambiarse más tarde en Configuración.</string> + <string name="onboarding_notifications_mode_subtitle">Puedes cambiar estos ajustes más tarde en Configuración.</string> <string name="onboarding_notifications_mode_service">Instantánea</string> - <string name="join_group_button">Únete</string> - <string name="join_group_incognito_button">Únete en modo incógnito</string> + <string name="join_group_button">Unirte</string> + <string name="join_group_incognito_button">Unirte en modo incógnito</string> <string name="conn_level_desc_indirect">indirecta (%1$s)</string> <string name="theme_light">Claro</string> <string name="chat_preferences_on">Activado</string> @@ -499,7 +496,7 @@ <string name="invalid_message_format">formato de mensaje no válido</string> <string name="live">EN VIVO</string> <string name="moderated_description">eliminado por el moderador</string> - <string name="display_name_invited_to_connect">invitado a conectarse</string> + <string name="display_name_invited_to_connect">invitación a conectarse</string> <string name="service_notifications_disabled">¡Las notificaciones instantáneas están desactivadas!</string> <string name="notification_preview_new_message">mensaje nuevo</string> <string name="notification_new_contact_request">Nueva solicitud de contacto</string> @@ -507,7 +504,7 @@ <string name="message_delivery_error_title">Error en la entrega del mensaje</string> <string name="message_delivery_error_desc">Lo más probable es que este contacto haya eliminado la conexión contigo.</string> <string name="moderate_verb">Moderar</string> - <string name="group_preview_join_as">unirse como %s</string> + <string name="group_preview_join_as">unirte como %s</string> <string name="images_limit_desc">Sólo se pueden enviar 10 imágenes al mismo tiempo</string> <string name="large_file">¡Archivo grande!</string> <string name="mute_chat">Silenciar</string> @@ -519,7 +516,7 @@ <string name="many_people_asked_how_can_it_deliver"><![CDATA[Muchos se preguntarán: <i>si SimpleX no tiene identificadores de usuario, ¿cómo puede entregar los mensajes\?</i>]]></string> <string name="incoming_video_call">Videollamada entrante</string> <string name="snd_group_event_user_left">has salido</string> - <string name="snd_conn_event_switch_queue_phase_completed">has cambiado la dirección</string> + <string name="snd_conn_event_switch_queue_phase_completed">has cambiado de servidor</string> <string name="feature_off">desactivado</string> <string name="v4_3_irreversible_message_deletion">Eliminación irreversible del mensaje</string> <string name="v4_3_voice_messages_desc">Máximo 40 segundos, recibido al instante.</string> @@ -544,7 +541,7 @@ <string name="no_received_app_files">Sin archivos recibidos o enviados</string> <string name="messages_section_title">Mensajes</string> <string name="new_passphrase">Contraseña nueva…</string> - <string name="join_group_question">¿Unirse al grupo\?</string> + <string name="join_group_question">¿Unirte al grupo?</string> <string name="joining_group">Entrando al grupo</string> <string name="keychain_error">Error Keystore</string> <string name="icon_descr_add_members">Invitar miembros</string> @@ -553,7 +550,7 @@ <string name="group_member_status_removed">expulsado</string> <string name="group_member_status_invited">ha sido invitado</string> <string name="no_contacts_to_add">Sin contactos que añadir</string> - <string name="new_member_role">Nuevo rol de miembro</string> + <string name="new_member_role">Nuevo rol del miembro</string> <string name="initial_member_role">Rol inicial</string> <string name="info_row_local_name">Nombre local</string> <string name="network_status">Estado de la red</string> @@ -564,10 +561,10 @@ <string name="settings_section_title_incognito">Modo incógnito</string> <string name="new_database_archive">Nuevo archivo de base de datos</string> <string name="old_database_archive">Archivo de bases de datos antiguas</string> - <string name="snd_conn_event_switch_queue_phase_completed_for_member">has cambiado la dirección por %s</string> + <string name="snd_conn_event_switch_queue_phase_completed_for_member">has cambiado el servidor para %s</string> <string name="rcv_group_event_member_left">ha salido</string> <string name="button_leave_group">Salir del grupo</string> - <string name="only_group_owners_can_change_prefs">Sólo los propietarios pueden modificar las preferencias de grupo.</string> + <string name="only_group_owners_can_change_prefs">Sólo los propietarios pueden modificar las preferencias del grupo.</string> <string name="users_delete_data_only">Sólo datos del perfil local</string> <string name="chat_preferences_no">no</string> <string name="thousand_abbreviation">k</string> @@ -620,7 +617,7 @@ <string name="image_descr_profile_image">imagen del perfil</string> <string name="prohibit_sending_voice_messages">No se permiten mensajes de voz.</string> <string name="protect_app_screen">Proteger la pantalla de la aplicación</string> - <string name="read_more_in_github_with_link"><![CDATA[Más información en nuestro <font color="#0088ff">repositorio GitHub</font> .]]></string> + <string name="read_more_in_github_with_link"><![CDATA[Saber más en nuestro <font color="#0088ff">repositorio GitHub</font> .]]></string> <string name="icon_descr_record_voice_message">Grabar mensaje de voz</string> <string name="rcv_group_event_member_deleted">ha expulsado a %1$s</string> <string name="send_link_previews">Enviar previsualizacion de enlaces</string> @@ -643,11 +640,11 @@ <string name="network_options_revert">Revertir</string> <string name="network_option_ping_interval">Intervalo PING</string> <string name="network_option_ping_count">Contador PING</string> - <string name="only_your_contact_can_delete">Sólo tu contacto puede eliminar mensajes de forma irreversible (tu puedes marcarlos para eliminar).</string> + <string name="only_your_contact_can_delete">Sólo tu contacto puede eliminar mensajes de forma irreversible (tu puedes marcarlos para eliminar). (24 horas)</string> <string name="v4_5_message_draft_descr">Conserva el último borrador del mensaje con los datos adjuntos.</string> <string name="v4_5_private_filenames">Nombres de archivos privados</string> <string name="v4_5_reduced_battery_usage">Reducción del uso de la batería</string> - <string name="observer_cant_send_message_desc">Póngase en contacto con el administrador del grupo.</string> + <string name="observer_cant_send_message_desc">Ponte en contacto con el administrador del grupo.</string> <string name="ask_your_contact_to_enable_voice">Solicita que tu contacto habilite el envío de mensajes de voz.</string> <string name="send_live_message">Mensaje en vivo</string> <string name="scan_QR_code">Escanear código QR</string> @@ -664,7 +661,7 @@ <string name="callstate_received_confirmation">confirmación recibida…</string> <string name="onboarding_notifications_mode_periodic">Periódico</string> <string name="privacy_redefined">Privacidad redefinida</string> - <string name="read_more_in_github">Más información en nuestro repositorio GitHub.</string> + <string name="read_more_in_github">Saber más en nuestro repositorio GitHub.</string> <string name="reject">Rechazar</string> <string name="open_verb">Abrir</string> <string name="icon_descr_call_pending_sent">Llamada pendiente</string> @@ -683,8 +680,8 @@ <string name="run_chat_section">EJECUTAR CHAT</string> <string name="restart_the_app_to_use_imported_chat_database">Reinicia la aplicación para poder usar la base de datos importada.</string> <string name="enter_correct_current_passphrase">Introduce la contraseña actual correcta.</string> - <string name="feature_received_prohibited">recepción prohibida</string> - <string name="only_you_can_delete_messages">Sólo tú puedes eliminar mensajes de forma irreversible (tu contacto puede marcarlos para eliminar).</string> + <string name="feature_received_prohibited">recepción no permitida</string> + <string name="only_you_can_delete_messages">Sólo tú puedes eliminar mensajes de forma irreversible (tu contacto puede marcarlos para eliminar). (24 horas)</string> <string name="prohibit_direct_messages">No se permiten mensajes directos entre miembros.</string> <string name="prohibit_sending_disappearing">No se permiten mensajes temporales.</string> <string name="v4_2_security_assessment">Evaluación de la seguridad</string> @@ -710,10 +707,10 @@ <string name="smp_servers_preset_server">Servidor predefinido</string> <string name="save_and_notify_contact">Guardar y notificar contacto</string> <string name="save_preferences_question">¿Guardar preferencias\?</string> - <string name="save_and_notify_group_members">Guardar y notificar a los miembros del grupo</string> + <string name="save_and_notify_group_members">Guardar y notificar grupo</string> <string name="connection_error_auth_desc">A menos que tu contacto haya eliminado la conexión o que este enlace ya se haya usado, podría ser un error. Por favor, notifícalo. \nPara conectarte, pide a tu contacto que cree otro enlace de conexión y comprueba que tienes buena conexión de red.</string> - <string name="periodic_notifications_desc">La aplicación recoge nuevos mensajes periódicamente por lo que usa un pequeño porcentaje de la batería al día. La aplicación no hace uso de notificaciones automáticas: los datos de tu dispositivo no se envían a los servidores.</string> + <string name="periodic_notifications_desc">La aplicación recoge nuevos mensajes periódicamente lo que consume un pequeño porcentaje de batería al día. La aplicación no usa notificaciones push por tanto los datos de tu dispositivo no se envían a los servidores push.</string> <string name="la_notice_title_simplex_lock">Bloqueo SimpleX</string> <string name="auth_unlock">Desbloquear</string> <string name="this_text_is_available_in_settings">Este texto está disponible en Configuración</string> @@ -722,7 +719,7 @@ <string name="using_simplex_chat_servers">Usando servidores SimpleX Chat.</string> <string name="network_session_mode_transport_isolation">Aislamiento de transporte</string> <string name="strikethrough_text">tachado</string> - <string name="use_chat">Usar Chat</string> + <string name="use_chat">Abrir SimpleX</string> <string name="settings_section_title_socks">PROXY SOCKS</string> <string name="settings_section_title_themes">TEMAS</string> <string name="stop_chat_confirmation">Detener</string> @@ -734,7 +731,7 @@ <string name="icon_descr_sent_msg_status_unauthorized_send">envío no autorizado</string> <string name="set_contact_name">Escribe un nombre para el contacto</string> <string name="unknown_error">Error desconocido</string> - <string name="member_role_will_be_changed_with_notification">El rol cambiará a \"%s\". Se notificará a todos los miembros del grupo.</string> + <string name="member_role_will_be_changed_with_notification">El rol del miembro cambiará a \"%s\" y se notificará al grupo.</string> <string name="v4_2_security_assessment_desc">La seguridad de SimpleX Chat ha sido auditada por Trail of Bits.</string> <string name="v4_4_disappearing_messages_desc">Los mensajes enviados se eliminarán una vez transcurrido el tiempo establecido.</string> <string name="ntf_channel_messages">Mensajes de chat SimpleX</string> @@ -764,8 +761,8 @@ <string name="add_contact_or_create_group">Inciar chat nuevo</string> <string name="stop_chat_to_export_import_or_delete_chat_database">Para exportar, importar o eliminar la base de datos debes detener Chat. Durante la parada no podrás recibir o enviar mensajes.</string> <string name="thank_you_for_installing_simplex">Gracias por instalar SimpleX Chat!</string> - <string name="to_protect_privacy_simplex_has_ids_for_queues">Para proteger la privacidad, en lugar de los identificadores de usuario que usan el resto de plataformas, SimpleX dispone de identificadores para las colas de mensajes, independientes para cada uno de tus contactos.</string> - <string name="la_notice_to_protect_your_information_turn_on_simplex_lock_you_will_be_prompted_to_complete_authentication_before_this_feature_is_enabled">Para proteger tu información, activa Bloqueo SimpleX. + <string name="to_protect_privacy_simplex_has_ids_for_queues">Para proteger tu privacidad, en lugar de los identificadores de usuario que usan el resto de plataformas, SimpleX dispone de identificadores para las colas de mensajes, independientes para cada uno de tus contactos.</string> + <string name="la_notice_to_protect_your_information_turn_on_simplex_lock_you_will_be_prompted_to_complete_authentication_before_this_feature_is_enabled">Para proteger tu información, activa el Bloqueo SimpleX. \nSe te pedirá que completes la autenticación antes de activar esta función.</string> <string name="updating_settings_will_reconnect_client_to_all_servers">Al actualizar la configuración, el cliente se reconectará a todos los servidores.</string> <string name="use_simplex_chat_servers__question">¿Usar servidores SimpleX Chat\?</string> @@ -811,7 +808,7 @@ <string name="settings_section_title_settings">CONFIGURACIÓN</string> <string name="stop_chat_question">¿Detener Chat\?</string> <string name="chat_item_ttl_seconds">%s segundo(s)</string> - <string name="group_invitation_tap_to_join">Pulsa para unirse</string> + <string name="group_invitation_tap_to_join">Pulsa para unirte</string> <string name="rcv_group_event_updated_group_profile">ha actualizado el perfil del grupo</string> <string name="network_option_tcp_connection_timeout">Tiempo de espera de la conexión TCP agotado</string> <string name="theme">Tema</string> @@ -822,7 +819,7 @@ <string name="update_database_passphrase">Actualizar contraseña base de datos</string> <string name="group_invitation_tap_to_join_incognito">Pulsa para unirte en modo incógnito</string> <string name="switch_verb">Cambiar</string> - <string name="member_role_will_be_changed_with_invitation">El rol cambiará a \"%s\". El miembro recibirá una nueva invitación.</string> + <string name="member_role_will_be_changed_with_invitation">El rol del miembro cambiará a \"%s\" y recibirá una invitación nueva.</string> <string name="update_network_settings_confirmation">Actualizar</string> <string name="update_network_settings_question">¿Actualizar la configuración de red\?</string> <string name="trying_to_connect_to_server_to_receive_messages">Intentando conectar con el servidor usado para recibir mensajes de este contacto.</string> @@ -838,7 +835,7 @@ <string name="chat_help_tap_button">Pulsa el botón</string> <string name="to_start_a_new_chat_help_header">Para iniciar un chat nuevo</string> <string name="switch_receiving_address">Cambiar servidor de recepción</string> - <string name="group_is_decentralized">Completamente descentralizado: sólo visible para los miembros.</string> + <string name="group_is_decentralized">Completamente descentralizado: sólo visible a los miembros.</string> <string name="to_connect_via_link_title">Para conectarte mediante enlace</string> <string name="smp_servers_test_failed">¡Error en prueba del servidor!</string> <string name="smp_servers_test_some_failed">Algunos servidores no superaron la prueba:</string> @@ -853,7 +850,7 @@ <string name="wrong_passphrase">Contraseña de base de datos incorrecta</string> <string name="wrong_passphrase_title">¡Contraseña incorrecta!</string> <string name="youve_accepted_group_invitation_connecting_to_inviting_group_member">Te has unido a este grupo. Conectando con el emisor de la invitacíon.</string> - <string name="alert_title_cant_invite_contacts_descr">Estás usando un perfil incógnito para este grupo, por tanto para evitar compartir tu perfil principal no se permite invitar a contactos</string> + <string name="alert_title_cant_invite_contacts_descr">Estás usando un perfil incógnito en este grupo. Para evitar descubrir tu perfil principal no se permite invitar contactos</string> <string name="you_are_invited_to_group">Has sido invitado al grupo</string> <string name="v4_3_voice_messages">Mensajes de voz</string> <string name="v4_3_irreversible_message_deletion_desc">Tus contactos pueden permitir la eliminación completa de mensajes.</string> @@ -883,7 +880,7 @@ <string name="alert_text_connection_pending_they_need_to_be_online_can_delete_and_retry">Tu contacto debe estar en línea para que se complete la conexión. \nPuedes cancelar esta conexión y eliminar el contacto (e intentarlo más tarde con un enlace nuevo).</string> <string name="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. -\nEsta acción no se puede deshacer. Tu perfil, contactos, mensajes y archivos se perderán irreversiblemente.</string> +\nEsta acción no podrá deshacerse. Tu perfil, contactos, mensajes y archivos actuales se perderán irreversiblemente.</string> <string name="incognito_random_profile">Tu perfil aleatorio</string> <string name="you_will_be_connected_when_your_connection_request_is_accepted">Te conectarás cuando tu solicitud se acepte, por favor espera o compruébalo más tarde.</string> <string name="you_will_be_connected_when_your_contacts_device_is_online">Te conectarás cuando el dispositivo de tu contacto esté en línea, por favor espera o compruébalo más tarde.</string> @@ -899,10 +896,10 @@ <string name="voice_message_with_duration">Mensaje de voz (%1$s )</string> <string name="network_use_onion_hosts_prefer">Si disponibles</string> <string name="we_do_not_store_contacts_or_messages_on_servers">No almacenamos ninguno de tus contactos o mensajes (una vez entregados) en los servidores.</string> - <string name="you_are_invited_to_group_join_to_connect_with_group_members">Has sido invitado al grupo. Únete para conectarte con los miembros del grupo.</string> + <string name="you_are_invited_to_group_join_to_connect_with_group_members">Has sido invitado a un grupo. Únete para conectar con sus miembros.</string> <string name="snd_group_event_member_deleted">has expulsado a %1$s</string> <string name="group_info_member_you">Tú: %1$s</string> - <string name="you_can_share_group_link_anybody_will_be_able_to_connect">Puedes compartir un enlace o un código QR: cualquiera podrá unirse al grupo. Si lo eliminas más tarde los miembros del grupo no se perderán.</string> + <string name="you_can_share_group_link_anybody_will_be_able_to_connect">Puedes compartir un enlace o código QR para que cualquiera pueda unirse al grupo. Si decides eliminarlo más tarde, los miembros del grupo se mantendrán.</string> <string name="incognito_info_share">Cuando compartes un perfil incógnito con alguien, este perfil también se usará para los grupos a los que te inviten.</string> <string name="your_preferences">Mis preferencias</string> <string name="v4_2_auto_accept_contact_requests_desc">Con mensaje de bienvenida opcional.</string> @@ -936,12 +933,12 @@ <string name="chat_preferences_you_allow">Permites</string> <string name="app_name">SimpleX</string> <string name="profile_will_be_sent_to_contact_sending_link">Tu perfil se enviará al contacto del que has recibido este enlace.</string> - <string name="you_will_join_group">Te unirás al grupo al que hace referencia este enlace y te conectarás con sus miembros.</string> + <string name="you_will_join_group">Te conectarás con todos los miembros del grupo.</string> <string name="sender_you_pronoun">tú</string> <string name="connected_to_server_to_receive_messages_from_contact">Estás conectado al servidor usado para recibir mensajes de este contacto.</string> <string name="description_via_contact_address_link">mediante enlace de dirección de contacto</string> <string name="description_via_group_link">mediante enlace de grupo</string> - <string name="description_you_shared_one_time_link">has compartido enlace de un solo uso</string> + <string name="description_you_shared_one_time_link">enlace de un solo uso</string> <string name="description_you_shared_one_time_link_incognito">has compartido enlace de un solo uso en módo incógnito</string> <string name="you_have_no_chats">No tienes chats</string> <string name="contact_sent_large_file">El contacto ha enviado un archivo mayor al máximo admitido (%1$s ).</string> @@ -970,17 +967,14 @@ <string name="error_saving_user_password">Error al guardar contraseña de usuario</string> <string name="relay_server_if_necessary">El retransmisor sólo se usa en caso de necesidad. Un tercero podría ver tu IP.</string> <string name="relay_server_protects_ip">El servidor de retransmisión protege tu IP pero puede ver la duración de la llamada.</string> - <string name="cant_delete_user_profile">¡No se puede eliminar el perfil!</string> <string name="enter_password_to_show">Introduce la contraseña</string> <string name="user_hide">Ocultar</string> <string name="user_mute">Silenciar</string> - <string name="save_and_update_group_profile">Guardar y actualizar perfil de grupo</string> + <string name="save_and_update_group_profile">Guardar y actualizar perfil del grupo</string> <string name="tap_to_activate_profile">Pulsa sobre un perfil para activarlo.</string> - <string name="should_be_at_least_one_visible_profile">Debe haber al menos un perfil de usuario visible.</string> <string name="user_unhide">Mostrar</string> <string name="button_welcome_message">Mensaje de bienvenida</string> <string name="group_welcome_title">Mensaje de bienvenida</string> - <string name="should_be_at_least_one_profile">Debe haber al menos un perfil de usuario.</string> <string name="make_profile_private">¡Hacer perfil privado!</string> <string name="dont_show_again">No mostrar de nuevo</string> <string name="muted_when_inactive">¡Silenciado cuando está inactivo!</string> @@ -1002,7 +996,7 @@ <string name="you_can_hide_or_mute_user_profile">Puedes ocultar o silenciar un perfil. Mantenlo pulsado para abrir el menú.</string> <string name="you_will_still_receive_calls_and_ntfs">Seguirás recibiendo llamadas y notificaciones de los perfiles silenciados cuando estén activos.</string> <string name="v4_6_group_moderation_descr">Ahora los administradores pueden: -\n- borrar mensajes de los miembros. +\n- eliminar mensajes de los miembros. \n- desactivar el rol miembro (a rol \"observador\")</string> <string name="to_reveal_profile_enter_password">Para hacer visible tu perfil oculto, introduce la contraseña completa en el campo de búsqueda del menú Mis perfiles.</string> <string name="database_upgrade">Actualización de la base de datos</string> @@ -1125,12 +1119,12 @@ <string name="learn_more">Más información</string> <string name="if_you_cant_meet_in_person">Si no puedes reunirte en persona, **muestra el código QR por videollamada**, o comparte el enlace.</string> <string name="scan_qr_to_connect_to_contact">Para conectarse, tu contacto puede escanear el código QR o usar el enlace en la aplicación.</string> - <string name="create_simplex_address">Crear tu dirección SimpleX</string> + <string name="create_simplex_address">Crear dirección SimpleX</string> <string name="auto_accept_contact">Auto aceptar</string> <string name="group_welcome_preview">Vista previa</string> <string name="opening_database">Abriendo base de datos…</string> <string name="error_setting_address">Error al introducir dirección</string> - <string name="read_more_in_user_guide_with_link"><![CDATA[Más información en la <font color="#0088ff">Guía de usuario</font>.]]></string> + <string name="read_more_in_user_guide_with_link"><![CDATA[Saber más en la <font color="#0088ff">Guía de Usuario</font>.]]></string> <string name="one_time_link_short">Enlace un uso</string> <string name="simplex_address">Dirección SimpleX</string> <string name="you_can_accept_or_reject_connection">Cuando alguien solicite conectarse podrás aceptar o rechazar su solicitud.</string> @@ -1162,7 +1156,7 @@ <string name="profile_update_will_be_sent_to_contacts">La actualización del perfil se enviará a tus contactos.</string> <string name="color_received_message">Mensaje recibido</string> <string name="save_auto_accept_settings">Guardar configuración de auto aceptar</string> - <string name="you_can_share_your_address">Puedes compartir tu dirección como enlace o como código QR: cualquiera podrá conectarse contigo.</string> + <string name="you_can_share_your_address">Puedes compartir tu dirección como enlace o código QR para que cualquiera pueda conectarse contigo.</string> <string name="save_settings_question">¿Guardar configuración\?</string> <string name="color_secondary">Secundario</string> <string name="color_sent_message">Mensaje enviado</string> @@ -1216,9 +1210,9 @@ <string name="current_version_timestamp">%s (actual)</string> <string name="share_text_sent_at">Enviado: %s</string> <string name="info_row_disappears_at">Desaparecerá</string> - <string name="message_reactions">Reacciones a los mensajes</string> + <string name="message_reactions">Reacciones a mensajes</string> <string name="prohibit_message_reactions">No se permiten reacciones a los mensajes.</string> - <string name="allow_message_reactions">Permitir reacciones a los mensajes.</string> + <string name="allow_message_reactions">Se permiten reacciones a los mensajes.</string> <string name="message_reactions_prohibited_in_this_chat">Las reacciones a los mensajes no están permitidas en este chat.</string> <string name="only_you_can_add_message_reactions">Sólo tú puedes añadir reacciones a los mensajes.</string> <string name="prohibit_message_reactions_group">No se permiten reacciones a los mensajes</string> @@ -1328,7 +1322,7 @@ <string name="v5_2_message_delivery_receipts">¡Confirmación de entrega de mensajes!</string> <string name="v5_2_more_things_descr">- entrega de mensajes más estable. \n- grupos un poco mejores. -\n- ¡y más!</string> +\n- ¡...y más!</string> <string name="sending_delivery_receipts_will_be_enabled">El envío de confirmaciones de entrega se activará para todos los contactos.</string> <string name="v5_2_message_delivery_receipts_descr">¡El doble check que nos faltaba! ✅</string> <string name="you_can_enable_delivery_receipts_later">Puedes activar más tarde en Configuración</string> @@ -1391,14 +1385,14 @@ <string name="error_creating_member_contact">Error al establecer contacto con el miembro</string> <string name="socks_proxy_setting_limitations"><![CDATA[<b>Atención</b>: los servidores de retransmisión están conectados mediante SOCKS proxy. Las llamadas y las previsualizaciones de enlaces usan conexión directa.]]></string> <string name="encrypt_local_files">Cifra archivos locales</string> - <string name="v5_3_new_desktop_app">Nueva aplicación para PC!</string> + <string name="v5_3_new_desktop_app">Nueva aplicación para ordenador!</string> <string name="v5_3_new_interface_languages">6 idiomas nuevos para el interfaz</string> <string name="v5_3_encrypt_local_files_descr">Cifrado de los nuevos archivos locales (excepto vídeos).</string> <string name="compose_send_direct_message_to_connect">Enviar mensaje directo para conectar</string> <string name="v5_3_discover_join_groups">Descubre y únete a grupos</string> <string name="v5_3_simpler_incognito_mode">Modo incógnito simplificado</string> <string name="v5_3_new_interface_languages_descr">Árabe, Búlgaro, Finlandés, Hebreo, Tailandés y Ucraniano - gracias a los usuarios y Weblate.</string> - <string name="v5_3_new_desktop_app_descr">Crea perfil nuevo en la aplicación para PC. 💻</string> + <string name="v5_3_new_desktop_app_descr">Crea perfil nuevo en la aplicación para ordenador. 💻</string> <string name="error_sending_message_contact_invitation">Error al enviar invitación</string> <string name="v5_3_simpler_incognito_mode_descr">Activa incógnito al conectar.</string> <string name="v5_3_discover_join_groups_descr">- conexión al servicio de directorio (BETA)! @@ -1407,62 +1401,158 @@ <string name="member_contact_send_direct_message">Enviar mensaje directo</string> <string name="rcv_group_event_member_created_contact">conectado directamente</string> <string name="expand_verb">Expandir</string> - <string name="encryption_renegotiation_error">Error en renegociación de cifrado</string> + <string name="encryption_renegotiation_error">Error de renegociación de cifrado</string> <string name="rcv_direct_event_contact_deleted">contacto eliminado</string> <string name="error_alert_title">Error</string> <string name="create_group_button">Crear grupo</string> <string name="create_another_profile_button">Crear perfil</string> - <string name="connected_desktop">Escritorio conectado</string> + <string name="connected_desktop">Ordenador conectado</string> <string name="new_mobile_device">Nuevo dispositivo móvil</string> - <string name="desktop_address">Dirección desktop</string> + <string name="desktop_address">Dirección ordenador</string> <string name="only_one_device_can_work_at_the_same_time">Sólo un dispositivo puede funcionar al mismo tiempo</string> <string name="connect_plan_join_your_group">¿Unirse a tu grupo?</string> - <string name="marked_deleted_items_description">%d mensajes marcados como borrados</string> + <string name="marked_deleted_items_description">%d mensaje(s) marcado(s) eliminado(s)</string> <string name="connect_plan_group_already_exists">¡El grupo ya existe!</string> - <string name="connect_plan_already_connecting">¡Ya está en proceso de conexión!</string> + <string name="connect_plan_already_connecting">¡Ya en proceso de conexión!</string> <string name="desktop_incompatible_version">Versión incompatible</string> <string name="new_desktop"><![CDATA[<i>(nuevo)</i>]]></string> - <string name="linked_desktop_options">Opciones escritorio enlazado</string> - <string name="linked_desktops">Desktop enlazados</string> - <string name="discover_on_network">Descubrir en red</string> - <string name="rcv_group_and_other_events">, y hay %d eventos más</string> + <string name="linked_desktop_options">Opciones ordenador enlazado</string> + <string name="linked_desktops">Ordenadores enlazados</string> + <string name="discover_on_network">Descubrir en red local</string> + <string name="rcv_group_and_other_events">y %d evento(s) más</string> <string name="connect_plan_connect_via_link">¿Conectar vía enlace?</string> - <string name="connect_plan_already_joining_the_group">¡Ya está en proceso de unirse al grupo!</string> - <string name="moderated_items_description">%d mensajes moderados por %s</string> + <string name="connect_plan_already_joining_the_group">¡En proceso de unirte al grupo!</string> + <string name="moderated_items_description">%1$d mensaje(s) moderado(s) por %2$s</string> <string name="connect_plan_connect_to_yourself">¿Conectarte a tí mismo?</string> <string name="linked_mobiles">Móviles enlazados</string> - <string name="desktop_device">Desktop</string> - <string name="connected_to_desktop">Conectado al escritorio</string> + <string name="desktop_device">Ordenador</string> + <string name="connected_to_desktop">Conectado con ordenador</string> <string name="loading_remote_file_title">Cargando archivo</string> - <string name="connecting_to_desktop">Conectando a desktop</string> - <string name="alert_text_encryption_renegotiation_failed">La renegociación de cifrado ha fallado.</string> - <string name="desktop_devices">Dispositivo desktop</string> + <string name="connecting_to_desktop">Conectando con ordenador</string> + <string name="alert_text_encryption_renegotiation_failed">Renegociación de cifrado fallida.</string> + <string name="desktop_devices">Ordenadores</string> <string name="correct_name_to">¿Corregir el nombre a %s?</string> <string name="delete_messages__question">Elimina %d mensajes?</string> <string name="link_a_mobile">Enlazar móvil</string> <string name="connect_with_contact_name_question">¿Conectar con %1$s?</string> <string name="block_member_confirmation">Bloquear</string> - <string name="blocked_items_description">%d mensajes bloqueados</string> + <string name="blocked_items_description">%d mensaje(s) bloqueado(s)</string> <string name="block_member_button">Bloquear miembro</string> <string name="connected_mobile">Móvil conectado</string> <string name="delete_and_notify_contact">Eliminar y notificar contacto</string> <string name="connect_plan_open_group">Grupo abierto</string> - <string name="desktop_connection_terminated">Conexión terminada</string> + <string name="desktop_connection_terminated">Conexión finalizada</string> <string name="this_device_version"><![CDATA[<i>(este dispositivo v%s)</i>]]></string> <string name="unblock_member_desc">¡Los mensajes de %s serán mostrados!</string> - <string name="enter_this_device_name">Introduce el nombre de este dispositivo…</string> + <string name="enter_this_device_name">Nombre de este dispositivo…</string> <string name="error">Error</string> - <string name="connect_to_desktop">Conectar a desktop</string> + <string name="connect_to_desktop">Conectar con ordenador</string> <string name="disconnect_remote_host">Desconectar</string> - <string name="block_member_question">Bloquear miembro?</string> - <string name="rcv_group_events_count">%d eventos de grupo</string> + <string name="block_member_question">¿Bloquear miembro?</string> + <string name="rcv_group_events_count">%d evento(s) de grupo</string> <string name="invalid_name">¡Nombre no válido!</string> <string name="connected_to_mobile">Conectado a móvil</string> - <string name="bad_desktop_address">Dirección de escritorio incorrecta</string> + <string name="bad_desktop_address">Dirección ordenador incorrecta</string> <string name="devices">Dispositivo</string> <string name="non_content_uri_alert_title">Ruta archivo no valida.</string> - <string name="disconnect_desktop_question">¿Desconectar desktop?</string> - <string name="block_member_desc">Los mensajes nuevos de %s estarán ocultos!</string> - <string name="desktop_app_version_is_incompatible">La versión de aplicación del desktop %s no es compatible con esta aplicación.</string> + <string name="disconnect_desktop_question">¿Desconectar ordenador?</string> + <string name="block_member_desc">¡Los mensajes nuevos de %s estarán ocultos!</string> + <string name="desktop_app_version_is_incompatible">La versión de aplicación del ordenador %s no es compatible con esta aplicación.</string> <string name="blocked_item_description">bloqueado</string> + <string name="v5_4_block_group_members">Bloquear miembros del grupo</string> + <string name="connect_plan_repeat_connection_request">¿Repetir solicitud de conexión?</string> + <string name="connect_plan_you_are_already_connecting_to_vName"><![CDATA[Ya estás conectando con <b>%1$s</b>.]]></string> + <string name="v5_4_incognito_groups_descr">Crear grupo usando perfil aleatorio.</string> + <string name="connect_plan_you_are_already_joining_the_group_via_this_link">Ya estás uniéndote al grupo mediante este enlace.</string> + <string name="refresh_qr_code">Recargar</string> + <string name="group_members_2">%s y %s</string> + <string name="multicast_connect_automatically">Conectar automáticamente</string> + <string name="connect_plan_you_are_already_joining_the_group_vName"><![CDATA[Ya estás uniéndote al grupo <b>%1$s</b>.]]></string> + <string name="v5_4_link_mobile_desktop">¡Enlazar aplicación móvil con ordenador!</string> + <string name="connect_plan_this_is_your_own_one_time_link">¡Este es tu propio enlace de un solo uso!</string> + <string name="v5_4_link_mobile_desktop_descr">Mediante protocolo seguro de resistencia cuántica.</string> + <string name="open_on_mobile_and_scan_qr_code"><![CDATA[Abre <i>Usar desde ordenador</i> en la aplicación móvil y escanea el código QR.]]></string> + <string name="v5_4_block_group_members_descr">Para ocultar mensajes no deseados.</string> + <string name="unlink_desktop_question">¿Desenlazar ordenador?</string> + <string name="v5_4_better_groups">Grupos mejorados</string> + <string name="video_decoding_exception_desc">El vídeo no puede ser decodificado. Por favor, prueba con otro vídeo o contacta con los desarrolladores.</string> + <string name="rcv_group_event_1_member_connected">%s conectado</string> + <string name="random_port">Aleatorio</string> + <string name="v5_4_incognito_groups">Grupos incógnito</string> + <string name="group_members_n">%s, %s y %d miembros</string> + <string name="this_device">Este dispositivo</string> + <string name="unblock_member_button">Desbloquear miembro</string> + <string name="remote_host_was_disconnected_toast"><![CDATA[Móvil <b>%s</b> desconectado]]></string> + <string name="waiting_for_desktop">Esperando ordenador…</string> + <string name="v5_4_better_groups_descr">Mensajería más segura y conexión más rápida.</string> + <string name="contact_tap_to_connect">Pulsa para conectar</string> + <string name="this_device_name">Nombre del dispositivo</string> + <string name="connect_plan_you_are_already_in_group_vName"><![CDATA[Ya estás en el grupo <b>%1$s</b>.]]></string> + <string name="connect_plan_this_is_your_own_simplex_address">¡Esta es tu propia dirección SimpleX!</string> + <string name="found_desktop">Ordenador encontrado</string> + <string name="not_compatible">¡No compatible!</string> + <string name="waiting_for_mobile_to_connect">Esperando conexión móvil:</string> + <string name="remove_member_button">Eliminar miembro</string> + <string name="unblock_member_question">¿Desbloquear miembro?</string> + <string name="open_port_in_firewall_desc">Para permitir que la aplicación móvil se conecte al ordenador, abre este puerto en el firewall si está habilitado</string> + <string name="settings_section_title_use_from_desktop">Usar desde ordenador</string> + <string name="session_code">Código de sesión</string> + <string name="connect_plan_repeat_join_request">¿Repetir solicitud de admisión?</string> + <string name="create_chat_profile">Crear perfil de chat</string> + <string name="button_remove_member_question">¿Eliminar miembro?</string> + <string name="connect_plan_you_are_already_connecting_via_this_one_time_link">¡Ya estás conectando mediante este enlace de un solo uso!</string> + <string name="unlink_desktop">Desenlazar</string> + <string name="this_device_name_shared_with_mobile">El nombre del dispositivo será compartido con el cliente móvil conectado.</string> + <string name="verify_code_on_mobile">Verificar código en móvil</string> + <string name="open_port_in_firewall_title">Abrir puerto en firewall</string> + <string name="non_content_uri_alert_text">Has compartido una ruta no válida. Informa a los desarrolladores del problema.</string> + <string name="disconnect_remote_hosts">Desconectar móviles</string> + <string name="group_member_role_author">autor</string> + <string name="paste_desktop_address">Pegar dirección de ordenador</string> + <string name="connect_plan_this_is_your_link_for_group_vName"><![CDATA[¡Este es tu enlace para el grupo <b>%1$s</b>!]]></string> + <string name="verify_code_with_desktop">Verificar código con ordenador</string> + <string name="scan_qr_code_from_desktop">Escanear código QR desde ordenador</string> + <string name="unblock_member_confirmation">Desbloquear</string> + <string name="multicast_discoverable_via_local_network">Detectable mediante red local</string> + <string name="v5_4_more_things_descr">- notificar opcionalmente a los contactos eliminados. +\n- nombres de perfil con espacios. +\n- ¡...y más!</string> + <string name="connect_plan_you_have_already_requested_connection_via_this_address">¡Ya has solicitado la conexión mediante esta dirección!</string> + <string name="terminal_always_visible">Mostrar consola en ventana nueva</string> + <string name="scan_from_mobile">Escáner desde móvil</string> + <string name="verify_connections">Verificar conexiones</string> + <string name="loading_remote_file_desc">Por favor, espere mientras el archivo se carga desde el móvil enlazado</string> + <string name="verify_connection">Verificar conexión</string> + <string name="no_connected_mobile">Ningún móvil conectado</string> + <string name="app_was_crashed">Error aplicación</string> + <string name="error_showing_content">error mostrando contenido</string> + <string name="error_showing_message">error mostrando mensaje</string> + <string name="you_can_make_address_visible_via_settings">Puedes hacerlo visible para tus contactos de SimpleX en Configuración.</string> + <string name="recent_history_is_not_sent_to_new_members">El historial no se envía a miembros nuevos.</string> + <string name="retry_verb">Reintentar</string> + <string name="camera_not_available">Cámara no disponible</string> + <string name="enable_sending_recent_history">Enviar hasta 100 últimos mensajes a los miembros nuevos.</string> + <string name="add_contact_button_to_create_link_or_connect_via_link"><![CDATA[<b>Añadir contacto</b>: crea un enlace de invitación nuevo o usa un enlace recibido.]]></string> + <string name="disable_sending_recent_history">No enviar historial a miembros nuevos.</string> + <string name="or_show_this_qr_code">O mostrar este código</string> + <string name="recent_history_is_sent_to_new_members">Hasta 100 últimos mensajes son enviados a los miembros nuevos.</string> + <string name="code_you_scanned_is_not_simplex_link_qr_code">El código QR escaneado no es un enlace SimpleX.</string> + <string name="the_text_you_pasted_is_not_a_link">El texto pegado no es un enlace SimpleX.</string> + <string name="enable_camera_access">Permitir acceso a la cámara</string> + <string name="you_can_view_invitation_link_again">Podrás ver el enlace de invitación en detalles de conexión.</string> + <string name="keep_unused_invitation_question">¿Guardar invitación no usada?</string> + <string name="share_this_1_time_link">Compartir este enlace de un uso</string> + <string name="create_group_button_to_create_new_group"><![CDATA[<b>Crear grupo</b>: crea un grupo nuevo.]]></string> + <string name="recent_history">Historial visible</string> + <string name="la_app_passcode">Código acceso app</string> + <string name="new_chat">Nuevo chat</string> + <string name="loading_chats">Cargando chats…</string> + <string name="creating_link">Creando enlace…</string> + <string name="or_scan_qr_code">O escanear código QR</string> + <string name="invalid_qr_code">Código QR no válido</string> + <string name="add_contact_tab">Añadir contacto</string> + <string name="tap_to_scan">Pulsa para escanear</string> + <string name="keep_invitation_link">Guardar</string> + <string name="tap_to_paste_link">Pulsa para pegar enlace</string> + <string name="search_or_paste_simplex_link">Buscar o pegar enlace SimpleX</string> </resources> \ No newline at end of file diff --git a/apps/multiplatform/common/src/commonMain/resources/MR/fa/strings.xml b/apps/multiplatform/common/src/commonMain/resources/MR/fa/strings.xml new file mode 100644 index 0000000000..47ea9f2e4b --- /dev/null +++ b/apps/multiplatform/common/src/commonMain/resources/MR/fa/strings.xml @@ -0,0 +1,116 @@ +<?xml version="1.0" encoding="utf-8"?> +<resources> + <string name="alert_text_decryption_error_n_messages_failed_to_decrypt">رمزگشایی %1$d پیام ناموفق بود.</string> + <string name="moderated_items_description">%1$d پیام توسط %2$s حذف شد</string> + <string name="integrity_msg_skipped">%1$d پیام از قلم افتاده</string> + <string name="group_info_section_title_num_members">%1$s عضو</string> + <string name="contact_wants_to_connect_via_call">%1$s می‌خواهد به شما متصل شود، به وسیله</string> + <string name="chat_item_ttl_day">1 روز</string> + <string name="send_disappearing_message_1_minute">1 دقیقه</string> + <string name="abort_switch_receiving_address_confirm">لغو</string> + <string name="abort_switch_receiving_address">لغو تغییر نشانی</string> + <string name="abort_switch_receiving_address_question">تغییر نشانی را لغو می‌کنید؟</string> + <string name="about_simplex">درباره سیمپل‌اکس(SimpleX)</string> + <string name="connect_via_contact_link">به وسیله نشانی مخاطب متصل می‌شوید؟</string> + <string name="connect_via_invitation_link">به وسیله لینک یک بار مصرف متصل می‌شوید؟</string> + <string name="connect_use_new_incognito_profile">از نمایه ناشناس جدید استفاده کن</string> + <string name="opening_database">در حال گشودن پایگاه داده…</string> + <string name="profile_will_be_sent_to_contact_sending_link">نمایه شما به مخاطبی که این لینک را از او دریافت کردید، فرستاده خواهد شد.</string> + <string name="connect_via_link_incognito">متصل شدن به صورت ناشناس</string> + <string name="non_content_uri_alert_text">شما یک مسیر نامعتبر پرونده به اشتراک گذاشتید. موضوع را به توسعه‌دهندگان برنامه گزارش دهید.</string> + <string name="receiving_files_not_yet_supported">هنوز از دریافت پرونده پشتیبانی نمی‌شود</string> + <string name="invalid_message_format">قالب پیام نامعتبر</string> + <string name="moderated_description">حذف شده</string> + <string name="error_showing_message">خطا در نمایش پیام</string> + <string name="trying_to_connect_to_server_to_receive_messages">در حال تلاش برای اتصال به سرور مورد استفاده برای دریافت پیام‌ها از این مخاطب.</string> + <string name="marked_deleted_items_description">%d پیام به عنوان حذف شده علامت گذاشته شد</string> + <string name="connected_to_server_to_receive_messages_from_contact">به سرور مورد استفاده برای دریافت پیام‌ها از این مخاطب متصل شده‌اید.</string> + <string name="server_connected">متصل</string> + <string name="server_error">خطا</string> + <string name="server_connecting">در حال اتصال</string> + <string name="thousand_abbreviation">k</string> + <string name="connect_via_group_link">به گروه می‌پیوندید؟</string> + <string name="connect_use_current_profile">از نمایه کنونی استفاده کن</string> + <string name="you_will_join_group">به تمام اعضای گروه متصل خواهید شد.</string> + <string name="connect_via_link_verb">متصل شدن</string> + <string name="non_content_uri_alert_title">مسیر نامعتبر پرونده</string> + <string name="app_was_crashed">برنامه از کار افتاد</string> + <string name="trying_to_connect_to_server_to_receive_messages_with_error">در حال تلاش برای اتصال به سرور مورد استفاده برای دریافت پیام‌ها از این مخاطب (خطا: %1$s).</string> + <string name="deleted_description">حذف شده</string> + <string name="marked_deleted_description">علامت گذاشته شده به عنوان حذف شده</string> + <string name="moderated_item_description">توسط %s حذف شد</string> + <string name="blocked_item_description">مسدود</string> + <string name="blocked_items_description">%d پیام مسدود شده</string> + <string name="sending_files_not_yet_supported">هنوز از ارسال پرونده پشتیبانی نمی‌شود</string> + <string name="sender_you_pronoun">شما</string> + <string name="unknown_message_format">قالب پیام ناشناخته</string> + <string name="live">زنده</string> + <string name="invalid_chat">گپ نامعتبر</string> + <string name="invalid_data">داده نامعتبر</string> + <string name="error_showing_content">خطا در نمایش محتوا</string> + <string name="decryption_error">خطا در رمزگشایی</string> + <string name="send_disappearing_message_5_minutes">5 دقیقه</string> + <string name="learn_more_about_address">درباره نشانی سیمپل‌اکس(SimpleX)</string> + <string name="one_time_link_short">لینک یک بار مصرف</string> + <string name="about_simplex_chat">درباره سیمپل‌اکس چت(SimpleX Chat)</string> + <string name="alert_text_decryption_error_too_many_skipped">%1$d پیام از قلم افتاد.</string> + <string name="chat_item_ttl_month">1 ماه</string> + <string name="chat_item_ttl_week">1 هفته</string> + <string name="v5_3_new_interface_languages">6 زبان جدید برای رابط کاربری</string> + <string name="send_disappearing_message_30_seconds">30 ثانیه</string> + <string name="description_you_shared_one_time_link_incognito">شما لینک یک بار مصرف ناشناس به اشتراک گذاشتید</string> + <string name="description_via_group_link">به وسیله لینک گروه</string> + <string name="description_via_group_link_incognito">ناشناس به وسیله لینک گروه</string> + <string name="description_via_contact_address_link">به وسیله لینک نشانی مخاطب</string> + <string name="description_via_one_time_link_incognito">ناشناس به وسیله لینک یک بار مصرف</string> + <string name="simplex_link_mode_description">توصیف</string> + <string name="simplex_link_mode_full">لینک کامل</string> + <string name="simplex_link_mode">لینک‌های SimpleX</string> + <string name="error_saving_smp_servers">خطا در ذخیره کردن سرورهای SMP</string> + <string name="error_saving_xftp_servers">خطا در ذخیره کردن سرورهای XFTP</string> + <string name="encryption_renegotiation_error">خطا در مذاکره مجدد رمزگذاری</string> + <string name="connection_local_display_name">اتصال %1$d</string> + <string name="display_name_connection_established">اتصال برقرار شد</string> + <string name="description_you_shared_one_time_link">شما لینک یک بار مصرف به اشتراک گذاشتید</string> + <string name="display_name_invited_to_connect">برای اتصال دعوت شده</string> + <string name="description_via_contact_address_link_incognito">ناشناس به وسیله لینک نشانی مخاطب</string> + <string name="description_via_one_time_link">به وسیله لینک یک بار مصرف</string> + <string name="simplex_link_group">لینک گروه SimpleX</string> + <string name="simplex_link_connection">به وسیله %1$s</string> + <string name="simplex_link_mode_browser">به وسیله مرورگر</string> + <string name="simplex_link_contact">نشانی مخاطب SimpleX</string> + <string name="simplex_link_invitation">دعوت یک بار مصرف SimpleX</string> + <string name="display_name_connecting">در حال اتصال…</string> + <string name="simplex_link_mode_browser_warning">باز کردن لینک در مرورگر ممکن است حریم خصوصی و امنیت اتصال را کاهش دهد. لینک‌های SimpleX ناموثق قرمز خواهند بود.</string> + <string name="error_loading_xftp_servers">خطا در بارگیری سرورهای XFTP</string> + <string name="failed_to_create_user_title">خطا در ایجاد نمایه!</string> + <string name="failed_to_active_user_title">خطا در تعویض نمایه!</string> + <string name="connection_timeout">توقف اتصال</string> + <string name="connection_error">خطا در اتصال</string> + <string name="error_sending_message">خطا در ارسال پیام</string> + <string name="error_creating_message">خطا در ایجاد پیام</string> + <string name="error_loading_details">خطا در بارگیری جزئیات</string> + <string name="error_joining_group">خطا در پیوستن به گروه</string> + <string name="sender_cancelled_file_transfer">فرستنده انتقال پرونده را لغو کرد.</string> + <string name="you_are_already_connected_to_vName_via_this_link">شما از قبل به %1$s متصل هستید.</string> + <string name="connection_error_auth">خطا در اتصال (تصدیق)</string> + <string name="error_loading_smp_servers">خطا در بارگیری سرورهای SMP</string> + <string name="failed_to_parse_chats_title">عدم موفقیت در بارگیری گپ‌ها</string> + <string name="contact_developers">لطفا برنامه را به‌روزرسانی کنید و با توسعه‌دهندگان تماس بگیرید.</string> + <string name="failed_to_create_user_duplicate_title">نام نمایشی همسان!</string> + <string name="failed_to_create_user_invalid_desc">نام نمایشی نامعتبر است. لطفا نام دیگری انتخاب کنید.</string> + <string name="error_adding_members">خطا در افزودن اعضا</string> + <string name="cannot_receive_file">امکان دریافت پرونده وجود ندارد</string> + <string name="network_error_desc">لطفا اتصال خود را با %1$s بررسی کنید و دوباره امتحان کنید.</string> + <string name="error_receiving_file">خطا در دریافت پرونده</string> + <string name="contact_already_exists">مخاطب از قبل وجود دارد</string> + <string name="invalid_connection_link">لینک اتصال نامعتبر</string> + <string name="please_check_correct_link_and_maybe_ask_for_a_new_one">لطفا بررسی کنید که از لینک صحیح استفاده کردید یا از مخاطبتان بخواهید لینک دیگری برایتان بفرستد.</string> + <string name="ensure_smp_server_address_are_correct_format_and_unique">مطمئن شوید قالب آدرس‌های سرور SMP صحیح است، در خط‌های جدا نوشته شده و تکرار نشده‌اند.</string> + <string name="error_setting_network_config">خطا در به‌روزرسانی پیکربندی شبکه</string> + <string name="failed_to_parse_chat_title">عدم موفقیت در بارگیری گپ</string> + <string name="failed_to_create_user_invalid_title">نام نمایشی نامعتبر!</string> + <string name="failed_to_create_user_duplicate_desc">شما یک نمایه گپ با نام نمایشی یکسان دارید، لطفا نام دیگری انتخاب کنید.</string> + <string name="error_creating_address">خطا در ایجاد نشانی</string> + <string name="ensure_xftp_server_address_are_correct_format_and_unique">مطمئن شوید قالب آدرس‌های سرور XFTP صحیح است، در خط‌های جدا نوشته شده و تکرار نشده‌اند.</string> +</resources> \ No newline at end of file diff --git a/apps/multiplatform/common/src/commonMain/resources/MR/fi/strings.xml b/apps/multiplatform/common/src/commonMain/resources/MR/fi/strings.xml index be4072c4bf..1434963263 100644 --- a/apps/multiplatform/common/src/commonMain/resources/MR/fi/strings.xml +++ b/apps/multiplatform/common/src/commonMain/resources/MR/fi/strings.xml @@ -188,7 +188,6 @@ <string name="allow_your_contacts_to_send_disappearing_messages">Salli kontaktiesi lähettää katoavia viestejä.</string> <string name="timed_messages">Katoavat viestit</string> <string name="icon_descr_context">Kontekstikuvake</string> - <string name="scan_QR_code_to_connect_to_contact_who_shows_QR_code"><![CDATA[<b>Skannaa QR-koodi</b>: muodostaaksesi yhteyden kontaktiisi, joka näyttää QR-koodin sinulle.]]></string> <string name="icon_descr_cancel_live_message">Peruuta live-viesti</string> <string name="configure_ICE_servers">Määritä ICE-palvelimet</string> <string name="add_address_to_your_profile">Lisää osoite profiiliisi, jotta kontaktisi voivat jakaa sen muiden kanssa. Profiilipäivitys lähetetään kontakteillesi.</string> @@ -231,7 +230,6 @@ <string name="clear_verb">Tyhjennä</string> <string name="clear_chat_button">Tyhjennä keskustelu</string> <string name="clear_chat_question">Tyhjennä keskustelu\?</string> - <string name="create_one_time_link">Luo kertaluonteinen kutsulinkki</string> <string name="app_version_name">Sovellusversio: v%s</string> <string name="callstatus_calling">soittaa…</string> <string name="delete_chat_profile">Poista keskusteluprofiili</string> @@ -271,7 +269,6 @@ <string name="icon_descr_server_status_disconnected">Katkaistu</string> <string name="back">Takaisin</string> <string name="connect_via_link_or_qr">Yhdistä linkillä / QR-koodilla</string> - <string name="add_new_contact_to_create_one_time_QR_code"><![CDATA[<b>Lisää uusi kontakti</b>: luo kertakäyttöinen QR-koodi kontaktille.]]></string> <string name="clear_chat_menu_action">Tyhjennä</string> <string name="desktop_scan_QR_code_from_app_via_scan_QR_code"><![CDATA[💻 työpöytä: skannaa esitetty QR-koodi sovelluksesta käyttämällä <b>Skannaa QR-koodi</b>.]]></string> <string name="delete_pending_connection__question">Poistetaanko odottava yhteys\?</string> @@ -338,7 +335,6 @@ <string name="share_text_disappears_at">Katoaa klo: %s</string> <string name="create_secret_group_title">Luo salainen ryhmä</string> <string name="chat_preferences_always">aina</string> - <string name="cant_delete_user_profile">Käyttäjäprofiilia ei voi poistaa!</string> <string name="allow_your_contacts_to_call">Salli kontaktiesi soittaa sinulle.</string> <string name="allow_your_contacts_irreversibly_delete">Salli kontaktiesi poistaa lähetetyt viestit peruuttamattomasti.</string> <string name="allow_your_contacts_to_send_voice_messages">Salli kontaktiesi lähettää ääniviestejä.</string> @@ -1241,8 +1237,6 @@ <string name="snd_conn_event_switch_queue_phase_completed_for_member">muutit osoitteeksi %s</string> <string name="invite_prohibited_description">Yrität kutsua kontaktia, jonka kanssa olet jakanut inkognito-profiilin, ryhmään, jossa käytät pääprofiiliasi</string> <string name="group_welcome_title">Tervetuloviesti</string> - <string name="should_be_at_least_one_profile">Käyttäjäprofiileja tulee olla vähintään yksi.</string> - <string name="should_be_at_least_one_visible_profile">Näkyviä käyttäjäprofiileja tulee olla vähintään yksi.</string> <string name="incognito_info_share">Kun jaat inkognitoprofiilin jonkun kanssa, tätä profiilia käytetään ryhmissä, joihin tämä sinut kutsuu.</string> <string name="group_main_profile_sent">Keskusteluprofiilisi lähetetään ryhmän jäsenille</string> <string name="incognito_random_profile">Satunnainen profiilisi</string> diff --git a/apps/multiplatform/common/src/commonMain/resources/MR/fr/strings.xml b/apps/multiplatform/common/src/commonMain/resources/MR/fr/strings.xml index 849daaeefe..43068ac7b6 100644 --- a/apps/multiplatform/common/src/commonMain/resources/MR/fr/strings.xml +++ b/apps/multiplatform/common/src/commonMain/resources/MR/fr/strings.xml @@ -111,14 +111,14 @@ <string name="share_verb">Partager</string> <string name="copy_verb">Copier</string> <string name="delete_verb">Supprimer</string> - <string name="save_verb">Sauvegarder</string> + <string name="save_verb">Enregistrer</string> <string name="edit_verb">Modifier</string> <string name="reveal_verb">Révéler</string> <string name="hide_verb">Cacher</string> <string name="allow_verb">Autoriser</string> <string name="delete_message__question">Supprimer le message \?</string> <string name="for_me_only">Supprimer pour moi</string> - <string name="your_chats">Chats</string> + <string name="your_chats">Discussions</string> <string name="notification_preview_mode_message">Texte du message</string> <string name="notification_preview_mode_hidden">Caché</string> <string name="la_notice_to_protect_your_information_turn_on_simplex_lock_you_will_be_prompted_to_complete_authentication_before_this_feature_is_enabled">Pour protéger vos informations, activez la fonction SimpleX Lock. @@ -132,7 +132,7 @@ <string name="notifications_mode_off">Exécuter lorsque l’app est ouverte</string> <string name="notifications_mode_service">Toujours activé</string> <string name="failed_to_parse_chat_title">Échec du chargement du chat</string> - <string name="failed_to_parse_chats_title">Échec du chargement des chats</string> + <string name="failed_to_parse_chats_title">Échec du chargement des discussions</string> <string name="contact_developers">Veuillez mettre à jour l’app et contacter les développeurs.</string> <string name="simplex_service_notification_text">Récupération des messages…</string> <string name="settings_notification_preview_title">Aperçu de notification</string> @@ -206,7 +206,6 @@ <string name="gallery_video_button">Vidéo</string> <string name="to_start_a_new_chat_help_header">Pour démarrer une nouvelle discussion</string> <string name="chat_help_tap_button">Appuyez sur le bouton</string> - <string name="scan_QR_code_to_connect_to_contact_who_shows_QR_code"><![CDATA[<b>Scanner un code QR</b> : pour vous connecter à votre contact qui vous montre un code QR.]]></string> <string name="to_connect_via_link_title">Pour se connecter via un lien</string> <string name="if_you_received_simplex_invitation_link_you_can_open_in_browser">Si vous avez reçu un lien d\'invitation SimpleX Chat, vous pouvez l\'ouvrir dans votre navigateur :</string> <string name="desktop_scan_QR_code_from_app_via_scan_QR_code"><![CDATA[💻 bureau : scanner le code QR affiché depuis l\'app, via <b>Scanner le code QR</b>.]]></string> @@ -246,7 +245,6 @@ <string name="paste_button">Coller</string> <string name="this_string_is_not_a_connection_link">Cette chaîne n\'est pas un lien de connexion !</string> <string name="you_can_also_connect_by_clicking_the_link"><![CDATA[Vous pouvez aussi vous connecter en cliquant sur le lien. Si il s\'ouvre dans le navigateur, cliquez sur <b>Ouvrir dans l\'app mobile</b>.]]></string> - <string name="create_one_time_link">Créer un lien d\'invitation unique</string> <string name="text_field_set_contact_placeholder">Définir le nom du contact…</string> <string name="icon_descr_server_status_disconnected">Déconnecté</string> <string name="icon_descr_server_status_error">Erreur</string> @@ -296,7 +294,6 @@ <string name="thank_you_for_installing_simplex">Merci d\'avoir installé SimpleX Chat !</string> <string name="you_can_connect_to_simplex_chat_founder"><![CDATA[Vous pouvez <font color="#0088ff">vous connecter aux développeurs de SimpleX Chat pour leur poser des questions et recevoir des réponses :</font>.]]></string> <string name="above_then_preposition_continuation">ci-dessus, puis :</string> - <string name="add_new_contact_to_create_one_time_QR_code"><![CDATA[<b>Ajouter un nouveau contact</b> : afin de créer un code QR à usage unique pour votre contact.]]></string> <string name="if_you_choose_to_reject_the_sender_will_not_be_notified">Si vous choisissez de la rejeter, l\'expéditeur·rice NE sera PAS notifié·e.</string> <string name="accept_contact_button">Accepter</string> <string name="mute_chat">Muet</string> @@ -332,7 +329,7 @@ <string name="chat_console">Console du chat</string> <string name="smp_servers">Serveurs SMP</string> <string name="smp_servers_test_servers">Tester les serveurs</string> - <string name="smp_servers_save">Sauvegarder les serveurs</string> + <string name="smp_servers_save">Enregistrer les serveurs</string> <string name="smp_servers_scan_qr">Scanner un code QR de serveur</string> <string name="smp_servers_use_server">Utiliser ce serveur</string> <string name="smp_servers_use_server_for_new_conn">Utiliser pour les nouvelles connexions</string> @@ -358,8 +355,8 @@ <string name="create_address">Créer une adresse</string> <string name="your_current_profile">Votre profil de chat</string> <string name="edit_image">Modifier l\'image</string> - <string name="save_and_notify_contacts">Sauvegarder et notifier les contacts</string> - <string name="save_and_notify_group_members">Sauvegarder et en informer les membres du groupe</string> + <string name="save_and_notify_contacts">Enregistrer et en informer les contacts</string> + <string name="save_and_notify_group_members">Enregistrer et en informer les membres du groupe</string> <string name="your_profile_is_stored_on_your_device">Votre profil, vos contacts et les messages reçus sont stockés sur votre appareil.</string> <string name="profile_is_only_shared_with_your_contacts">Le profil n\'est partagé qu\'avec vos contacts.</string> <string name="display_name_cannot_contain_whitespace">Le nom d\'affichage ne peut pas contenir d\'espace.</string> @@ -378,7 +375,7 @@ <string name="opensource_protocol_and_code_anybody_can_run_servers">Protocole et code open-source – n\'importe qui peut heberger un serveur.</string> <string name="to_protect_privacy_simplex_has_ids_for_queues">Pour protéger votre vie privée, au lieu d\'IDs utilisés par toutes les autres plateformes, SimpleX possède des IDs pour les queues de messages, distinctes pour chacun de vos contacts.</string> <string name="read_more_in_github">Plus d\'informations sur notre GitHub.</string> - <string name="paste_the_link_you_received">Coller le lien reçu</string> + <string name="paste_the_link_you_received">Collez le lien que vous avez reçu</string> <string name="use_chat">Utiliser le chat</string> <string name="onboarding_notifications_mode_title">Notifications privées</string> <string name="onboarding_notifications_mode_subtitle">Peut être modifié ultérieurement via les paramètres.</string> @@ -389,10 +386,10 @@ <string name="about_simplex_chat">À propos de SimpleX Chat</string> <string name="how_to_use_simplex_chat">Comment l\'utiliser</string> <string name="markdown_help">Aide Markdown</string> - <string name="save_servers_button">Sauvegarder</string> + <string name="save_servers_button">Enregistrer</string> <string name="network_and_servers">Réseau et serveurs</string> - <string name="save_and_notify_contact">Sauvegarder et en informer les contacts</string> - <string name="exit_without_saving">Quitter sans sauvegarder</string> + <string name="save_and_notify_contact">Enregistrer et en informer le contact</string> + <string name="exit_without_saving">Quitter sans enregistrer</string> <string name="callstatus_rejected">appel rejeté</string> <string name="callstatus_in_progress">appel en cours</string> <string name="callstatus_ended">appel terminé %1$s</string> @@ -431,7 +428,7 @@ <string name="full_name__field">Nom complet :</string> <string name="your_profile_is_stored_on_device_and_shared_only_with_contacts_simplex_cannot_see_it">Votre profil est stocké sur votre appareil et partagé uniquement avec vos contacts. Les serveurs SimpleX ne peuvent pas voir votre profil.</string> <string name="delete_image">Supprimer l\'image</string> - <string name="save_preferences_question">Sauvegarder les préférences \?</string> + <string name="save_preferences_question">Enregistrer les préférences ?</string> <string name="you_control_your_chat">Vous maîtrisez vos discussions !</string> <string name="the_messaging_and_app_platform_protecting_your_privacy_and_security">La plateforme de messagerie et d\'applications qui protège votre vie privée et votre sécurité.</string> <string name="we_do_not_store_contacts_or_messages_on_servers">Nous ne stockons aucun de vos contacts ou messages (une fois délivrés) sur les serveurs.</string> @@ -500,7 +497,7 @@ <string name="icon_descr_call_ended">Appel terminé</string> <string name="your_privacy">Votre vie privée</string> <string name="settings_section_title_device">APPAREIL</string> - <string name="settings_section_title_chats">CHATS</string> + <string name="settings_section_title_chats">DISCUSSIONS</string> <string name="settings_developer_tools">Outils du développeur</string> <string name="settings_section_title_icon">ICONE DE L\'APP</string> <string name="your_chat_database">Votre base de données de chat</string> @@ -509,7 +506,7 @@ <string name="restart_the_app_to_use_imported_chat_database">Redémarrez l\'application pour utiliser la base de données de chat importée.</string> <string name="chat_item_ttl_day">1 jour</string> <string name="delete_messages">Supprimer les messages</string> - <string name="save_passphrase_in_keychain">Sauvegarder la phrase secrète dans le keystore</string> + <string name="save_passphrase_in_keychain">Enregistrer la phrase secrète dans le Keystore</string> <string name="database_encrypted">Base de données chiffrée !</string> <string name="error_encrypting_database">Erreur lors du chiffrement de la base de données</string> <string name="update_database">Mise à jour</string> @@ -652,7 +649,7 @@ <string name="keychain_error">Erreur de la keychain</string> <string name="file_with_path">Fichier : %s</string> <string name="database_passphrase_is_required">La phrase secrète de la base de données est nécessaire pour ouvrir le chat.</string> - <string name="save_passphrase_and_open_chat">Sauvegarder la phrase secrète et ouvrir le chat</string> + <string name="save_passphrase_and_open_chat">Enregistrer la phrase secrète et ouvrir le chat</string> <string name="open_chat">Ouvrir le chat</string> <string name="database_backup_can_be_restored">La tentative de modification de la phrase secrète de la base de données n\'a pas abouti.</string> <string name="restore_database_alert_title">Restaurer la sauvegarde de la base de données \?</string> @@ -661,7 +658,7 @@ <string name="you_can_start_chat_via_setting_or_by_restarting_the_app">Vous pouvez lancer le chat via les Paramètres / la Base de données de l\'app ou en la redémarrant.</string> <string name="chat_archive_header">Archives du chat</string> <string name="chat_archive_section">ARCHIVE DU CHAT</string> - <string name="save_archive">Sauvegarder l\'archive</string> + <string name="save_archive">Enregistrer l\'archive</string> <string name="delete_archive">Supprimer l\'archive</string> <string name="delete_chat_archive_question">Supprimer l\'archive du chat \?</string> <string name="group_invitation_item_description">Invitation au groupe %1$s</string> @@ -764,13 +761,13 @@ <string name="chat_preferences_off">off</string> <string name="direct_messages">Messages directs</string> <string name="full_deletion">Supprimer pour tous</string> - <string name="only_you_can_delete_messages">Vous êtes le seul à pouvoir supprimer des messages de manière irréversible (votre contact peut les marquer comme supprimé).</string> + <string name="only_you_can_delete_messages">Vous êtes le seul à pouvoir supprimer des messages de manière irréversible (votre contact peut les marquer comme supprimé). (24 heures)</string> <string name="conn_stats_section_title_servers">SERVEURS</string> <string name="receiving_via">Réception via</string> <string name="theme_system">Système</string> <string name="allow_direct_messages">Autoriser l\'envoi de messages directs aux membres.</string> <string name="prohibit_direct_messages">Interdire l\'envoi de messages directs aux membres.</string> - <string name="group_members_can_delete">Les membres du groupe peuvent supprimer de manière irréversible les messages envoyés.</string> + <string name="group_members_can_delete">Les membres du groupe peuvent supprimer de manière irréversible les messages envoyés. (24 heures)</string> <string name="message_deletion_prohibited_in_chat">La suppression irréversible de messages est interdite dans ce groupe.</string> <string name="sending_via">Envoi via</string> <string name="network_status">État du réseau</string> @@ -778,7 +775,7 @@ <string name="create_secret_group_title">Créer un groupe secret</string> <string name="group_main_profile_sent">Votre profil de chat sera envoyé aux membres du groupe</string> <string name="network_option_enable_tcp_keep_alive">Activer le TCP keep-alive</string> - <string name="network_options_save">Sauvegarder</string> + <string name="network_options_save">Enregistrer</string> <string name="update_network_settings_question">Mettre à jour les paramètres réseau \?</string> <string name="incognito">Incognito</string> <string name="incognito_random_profile">Votre profil aléatoire</string> @@ -786,7 +783,7 @@ <string name="theme_light">Clair</string> <string name="theme_dark">Sombre</string> <string name="theme">Thème</string> - <string name="save_color">Sauvegarder la couleur</string> + <string name="save_color">Enregistrer la couleur</string> <string name="reset_color">Réinitialisation des couleurs</string> <string name="color_primary">Principale</string> <string name="chat_preferences_you_allow">Vous autorisez</string> @@ -799,14 +796,14 @@ <string name="group_preferences">Préférences du groupe</string> <string name="set_group_preferences">Définir les préférences du groupe</string> <string name="your_preferences">Vos préférences</string> - <string name="allow_your_contacts_irreversibly_delete">Autorise vos contacts à supprimer de manière irréversible les messages envoyés.</string> + <string name="allow_your_contacts_irreversibly_delete">Autorise vos contacts à supprimer de manière irréversible les messages envoyés. (24 heures)</string> <string name="contacts_can_mark_messages_for_deletion">Vos contacts peuvent marquer les messages pour les supprimer ; vous pourrez les consulter.</string> <string name="allow_your_contacts_to_send_voice_messages">Autorise vos contacts à envoyer des messages vocaux.</string> <string name="allow_voice_messages_only_if">Autoriser les messages vocaux uniquement si votre contact les autorise.</string> <string name="prohibit_sending_voice_messages">Interdire l\'envoi de messages vocaux.</string> <string name="only_you_can_send_disappearing">Seulement vous pouvez envoyer des messages éphémères.</string> <string name="only_you_can_send_voice">Vous seul pouvez envoyer des messages vocaux.</string> - <string name="allow_to_delete_messages">Autoriser la suppression irréversible de messages envoyés.</string> + <string name="allow_to_delete_messages">Autoriser la suppression irréversible de messages envoyés. (24 heures)</string> <string name="disappearing_messages_are_prohibited">Les messages éphémères sont interdits dans ce groupe.</string> <string name="group_members_can_send_voice">Les membres du groupe peuvent envoyer des messages vocaux.</string> <string name="delete_after">Supprimer après</string> @@ -844,8 +841,8 @@ <string name="incognito_info_share">Lorsque vous partagez un profil incognito avec quelqu\'un, ce profil sera utilisé pour les groupes auxquels il vous invite.</string> <string name="chat_preferences_yes">oui</string> <string name="allow_disappearing_messages_only_if">Autorise les messages éphémères seulement si votre contact les autorises.</string> - <string name="allow_irreversible_message_deletion_only_if">Autoriser la suppression irréversible des messages uniquement si votre contact vous l\'autorise.</string> - <string name="only_your_contact_can_delete">Seul votre contact peut supprimer de manière irréversible des messages (vous pouvez les marquer comme supprimé).</string> + <string name="allow_irreversible_message_deletion_only_if">Autoriser la suppression irréversible des messages uniquement si votre contact vous l\'autorise. (24 heures)</string> + <string name="only_your_contact_can_delete">Seul votre contact peut supprimer de manière irréversible des messages (vous pouvez les marquer comme supprimé). (24 heures)</string> <string name="only_your_contact_can_send_disappearing">Seulement votre contact peut envoyer des messages éphémères.</string> <string name="both_you_and_your_contact_can_send_disappearing">Vous et votre contact êtes tous deux en mesure d\'envoyer des messages éphémères.</string> <string name="voice_messages_are_prohibited">Les messages vocaux sont interdits dans ce groupe.</string> @@ -856,12 +853,12 @@ <string name="network_option_seconds_label">sec</string> <string name="network_option_tcp_connection_timeout">Délai de connexion TCP</string> <string name="group_profile_is_stored_on_members_devices">Le profil du groupe est stocké sur les appareils des membres, pas sur les serveurs.</string> - <string name="save_group_profile">Sauvegarder le profil du groupe</string> + <string name="save_group_profile">Enregistrer le profil du groupe</string> <string name="error_saving_group_profile">Erreur lors de la sauvegarde du profil de groupe</string> <string name="network_options_reset_to_defaults">Réinitialisation des valeurs par défaut</string> <string name="network_option_protocol_timeout">Délai du protocole</string> <string name="network_option_ping_interval">Intervalle de PING</string> - <string name="both_you_and_your_contacts_can_delete">Vous et votre contact êtes tous deux en mesure de supprimer de manière irréversible les messages envoyés.</string> + <string name="both_you_and_your_contacts_can_delete">Vous et votre contact êtes tous deux en mesure de supprimer de manière irréversible les messages envoyés. (24 heures)</string> <string name="message_deletion_prohibited">La suppression irréversible de message est interdite dans ce chat.</string> <string name="both_you_and_your_contact_can_send_voice">Vous et votre contact êtes tous deux en mesure d\'envoyer des messages vocaux.</string> <string name="only_your_contact_can_send_voice">Seul votre contact peut envoyer des messages vocaux.</string> @@ -901,8 +898,8 @@ <string name="invalid_data">données invalides</string> <string name="invalid_chat">chat invalide</string> <string name="icon_descr_cancel_live_message">Annuler le message dynamique</string> - <string name="feature_offered_item">offert %s</string> - <string name="feature_offered_item_with_param">offert %s: %2s</string> + <string name="feature_offered_item">propose %s</string> + <string name="feature_offered_item_with_param">propose %s : %2s</string> <string name="feature_cancelled_item">annulé %s</string> <string name="app_version_title">Version de l\'app</string> <string name="core_simplexmq_version">simplexmq : v%s (%2s)</string> @@ -962,10 +959,9 @@ <string name="observer_cant_send_message_title">Vous ne pouvez pas envoyer de messages !</string> <string name="group_member_role_observer">observateur</string> <string name="language_system">Système</string> - <string name="smp_save_servers_question">Sauvegarder les serveurs \?</string> + <string name="smp_save_servers_question">Enregistrer les serveurs ?</string> <string name="dont_show_again">Ne plus afficher</string> <string name="button_add_welcome_message">Ajouter un message d\'accueil</string> - <string name="cant_delete_user_profile">Impossible de supprimer le profil d\'utilisateur !</string> <string name="v4_6_group_moderation">Modération de groupe</string> <string name="user_hide">Cacher</string> <string name="muted_when_inactive">Mute en cas d\'inactivité !</string> @@ -982,7 +978,7 @@ <string name="v4_6_group_moderation_descr">Désormais, les administrateurs peuvent : \n- supprimer les messages des membres. \n- désactiver des membres (rôle \"observateur\")</string> - <string name="save_welcome_message_question">Sauvegarder le message d\'accueil \?</string> + <string name="save_welcome_message_question">Enregistrer le message d\'accueil ?</string> <string name="v4_6_group_welcome_message_descr">Choisissez un message à l\'attention des nouveaux membres !</string> <string name="hide_profile">Masquer le profil</string> <string name="v4_6_reduced_battery_usage_descr">D\'autres améliorations sont à venir !</string> @@ -991,13 +987,11 @@ <string name="user_mute">Mute</string> <string name="v4_6_hidden_chat_profiles_descr">Protégez vos profils de chat par un mot de passe !</string> <string name="tap_to_activate_profile">Appuyez pour activer un profil.</string> - <string name="save_and_update_group_profile">Sauvegarder et mettre à jour le profil du groupe</string> + <string name="save_and_update_group_profile">Enregistrer et mettre à jour le profil du groupe</string> <string name="save_profile_password">Enregistrer le mot de passe du profil</string> <string name="to_reveal_profile_enter_password">Pour révéler votre profil caché, entrez le mot de passe dans le champ de recherche de la page Profils de chat.</string> <string name="v4_6_audio_video_calls_descr">Prise en charge du Bluetooth et autres améliorations.</string> <string name="v4_6_chinese_spanish_interface_descr">Merci aux utilisateurs - contribuez via Weblate !</string> - <string name="should_be_at_least_one_profile">Il doit y avoir au moins un profil d\'utilisateur.</string> - <string name="should_be_at_least_one_visible_profile">Il doit y avoir au moins un profil d\'utilisateur visible.</string> <string name="user_unhide">Dévoiler</string> <string name="user_unmute">Démute</string> <string name="button_welcome_message">Message d\'accueil</string> @@ -1136,7 +1130,7 @@ <string name="stop_sharing_address">Cesser le partage d\'adresse \?</string> <string name="invite_friends">Inviter des amis</string> <string name="email_invite_subject">Discutons sur SimpleX Chat</string> - <string name="save_settings_question">Sauvegarder les paramètres \?</string> + <string name="save_settings_question">Enregistrer les paramètres ?</string> <string name="dont_create_address">Ne pas créer d\'adresse</string> <string name="address_section_title">Adresse</string> <string name="share_address">Partager l\'adresse</string> @@ -1173,7 +1167,7 @@ <string name="import_theme_error_desc">Assurez-vous que le fichier a une syntaxe YAML correcte. Exporter le thème pour avoir un exemple de la structure du fichier du thème.</string> <string name="profile_update_will_be_sent_to_contacts">La mise à jour du profil sera envoyée à vos contacts.</string> <string name="read_more_in_user_guide_with_link"><![CDATA[Pour en savoir plus, consultez le <font color="#0088ff">Guide de l\'utilisateur</font>.]]></string> - <string name="save_auto_accept_settings">Sauvegarder les paramètres d\'acceptation automatique</string> + <string name="save_auto_accept_settings">Enregistrer les paramètres de validation automatique</string> <string name="scan_qr_to_connect_to_contact">Pour se connecter, votre contact peut scanner le code QR ou utiliser le lien dans l\'application.</string> <string name="app_passcode_replaced_with_self_destruct">Le code d\'accès de l\'application est remplacé par un code d\'autodestruction.</string> <string name="enable_self_destruct">Activer l\'autodestruction</string> @@ -1218,7 +1212,7 @@ <string name="error_loading_details">Erreur de chargement des détails</string> <string name="edit_history">Historique</string> <string name="info_menu">Info</string> - <string name="search_verb">Recherche</string> + <string name="search_verb">Rechercher</string> <string name="received_message">Message reçu</string> <string name="custom_time_picker_custom">personnalisé</string> <string name="custom_time_picker_select">Choisir</string> @@ -1267,7 +1261,7 @@ <string name="only_owners_can_enable_files_and_media">Seuls les propriétaires du groupe peuvent activer les fichiers et les médias.</string> <string name="favorite_chat">Favoris</string> <string name="prohibit_sending_files">Interdire l\'envoi de fichiers et de médias.</string> - <string name="no_filtered_chats">Pas de chats filtrés</string> + <string name="no_filtered_chats">Aucune discussion filtrés</string> <string name="files_and_media">Fichiers et médias</string> <string name="unfavorite_chat">Défavoris</string> <string name="network_option_protocol_timeout_per_kb">Délai d\'attente du protocole par KB</string> @@ -1297,7 +1291,7 @@ <string name="receipts_contacts_enable_keep_overrides">Activer (conserver les remplacements)</string> <string name="snd_conn_event_ratchet_sync_agreed">chiffrement accepté pour %s</string> <string name="v5_2_favourites_filter_descr">Filtrer les messages non lus et favoris.</string> - <string name="v5_2_favourites_filter">Trouver des messages plus rapidement</string> + <string name="v5_2_favourites_filter">Recherche de message plus rapide</string> <string name="in_reply_to">En réponse à</string> <string name="v5_2_more_things_descr">- une diffusion plus stable des messages. \n- des groupes un peu plus performants. @@ -1319,7 +1313,7 @@ <string name="snd_conn_event_ratchet_sync_ok">chiffrement ok pour %s</string> <string name="snd_conn_event_ratchet_sync_allowed">renégociation de chiffrement autorisée pour %s</string> <string name="sender_at_ts">%s à %s</string> - <string name="send_receipts">Envoyer les justificatifs</string> + <string name="send_receipts">Envoi de justificatifs</string> <string name="fix_connection_confirm">Réparer</string> <string name="fix_connection">Réparer la connexion</string> <string name="fix_connection_question">Réparer la connexion\?</string> @@ -1344,7 +1338,7 @@ <string name="receipts_groups_override_enabled">L\'envoi de reçus est activé pour %d groupes</string> <string name="receipts_groups_disable_for_all">Désactivé pour tous les groupes</string> <string name="send_receipts_disabled_alert_title">Les accusés de réception sont désactivés</string> - <string name="in_developing_desc">Cette fonctionnalité n\'est pas encore prise en charge. Essayez la dans la prochaine version.</string> + <string name="in_developing_desc">Cette fonctionnalité est indisponible. Essayez la une prochaine version.</string> <string name="delivery">Distribution</string> <string name="send_receipts_disabled">désactivé</string> <string name="no_info_on_delivery">Pas d\'information sur la distribution</string> @@ -1407,14 +1401,14 @@ <string name="expand_verb">Développer</string> <string name="connect_plan_repeat_connection_request">Répéter la demande de connexion ?</string> <string name="rcv_direct_event_contact_deleted">contact supprimé</string> - <string name="connect_plan_you_are_already_connecting_to_vName">Vous êtes déjà connecté(e) à %1$s.</string> + <string name="connect_plan_you_are_already_connecting_to_vName"><![CDATA[Vous êtes déjà connecté(e) à <b>%1$s</b>.]]></string> <string name="error_alert_title">Erreur</string> <string name="connect_plan_you_are_already_joining_the_group_via_this_link">Vous êtes déjà en train de rejoindre le groupe via ce lien.</string> <string name="create_group_button">Créer un groupe</string> <string name="create_another_profile_button">Créer le profil</string> <string name="group_members_2">%s et %s</string> <string name="connect_plan_join_your_group">Rejoindre votre groupe ?</string> - <string name="connect_plan_you_are_already_joining_the_group_vName">Vous êtes déjà en train de rejoindre le groupe %1$s.</string> + <string name="connect_plan_you_are_already_joining_the_group_vName"><![CDATA[Vous êtes déjà en train de rejoindre le groupe <b>%1$s</b>.]]></string> <string name="connect_plan_this_is_your_own_one_time_link">Voici votre propre lien unique !</string> <string name="marked_deleted_items_description">%d messages marqués comme supprimés</string> <string name="connect_plan_group_already_exists">Ce groupe existe déjà !</string> @@ -1425,11 +1419,11 @@ <string name="connect_plan_connect_via_link">Se connecter via un lien ?</string> <string name="connect_plan_already_joining_the_group">Groupe déjà rejoint !</string> <string name="group_members_n">%s, %s et %d membres</string> - <string name="moderated_items_description">%d messages modérés par %s</string> + <string name="moderated_items_description">%1$d messages modérés par %2$s</string> <string name="unblock_member_button">Débloquer ce membre</string> <string name="connect_plan_connect_to_yourself">Se connecter à soi-même ?</string> <string name="contact_tap_to_connect">Tapez pour vous connecter</string> - <string name="connect_plan_you_are_already_in_group_vName">Vous êtes déjà dans le groupe %1$s.</string> + <string name="connect_plan_you_are_already_in_group_vName"><![CDATA[Vous êtes déjà dans le groupe <b>%1$s</b>.]]></string> <string name="connect_plan_this_is_your_own_simplex_address">Voici votre propre adresse SimpleX !</string> <string name="correct_name_to">Corriger le nom pour %s ?</string> <string name="delete_messages__question">Supprimer %d messages ?</string> @@ -1450,7 +1444,7 @@ <string name="block_member_question">Bloquer ce membre ?</string> <string name="rcv_group_events_count">%d événements de groupe</string> <string name="invalid_name">Nom invalide !</string> - <string name="connect_plan_this_is_your_link_for_group_vName">Voici votre lien pour le groupe %1$s !</string> + <string name="connect_plan_this_is_your_link_for_group_vName"><![CDATA[Voici votre lien pour le groupe <b>%1$s</b> !]]></string> <string name="unblock_member_confirmation">Débloquer</string> <string name="non_content_uri_alert_title">Chemin du fichier invalide</string> <string name="connect_plan_you_have_already_requested_connection_via_this_address">Vous avez déjà demandé une connexion via cette adresse !</string> @@ -1483,13 +1477,13 @@ <string name="linked_mobiles">Mobiles liés</string> <string name="desktop_device">Bureau</string> <string name="connected_to_desktop">Connecté au bureau</string> - <string name="this_device_name">Ce nom d\'appareil</string> + <string name="this_device_name">Nom de cet appareil</string> <string name="waiting_for_mobile_to_connect">En attente d\'une connexion mobile:</string> <string name="loading_remote_file_title">Chargement du fichier</string> <string name="connecting_to_desktop">Connexion au bureau</string> <string name="desktop_devices">Appareils de bureau</string> <string name="link_a_mobile">Lier un portable</string> - <string name="settings_section_title_use_from_desktop">Utilisation depuis le bureau</string> + <string name="settings_section_title_use_from_desktop">Accès au bureau</string> <string name="connected_mobile">Mobile connecté</string> <string name="session_code">Code de session</string> <string name="desktop_connection_terminated">Connexion terminée</string> @@ -1499,14 +1493,14 @@ <string name="verify_code_on_mobile">Vérifier le code sur le mobile</string> <string name="enter_this_device_name">Entrez le nom de l\'appareil…</string> <string name="error">Erreur</string> - <string name="connect_to_desktop">Se connecter au bureau</string> + <string name="connect_to_desktop">Connexion au bureau</string> <string name="disconnect_remote_host">Se déconnecter</string> <string name="group_member_role_author">auteur</string> <string name="connected_to_mobile">Connecté au portable</string> <string name="bad_desktop_address">Mauvaise adresse de bureau</string> <string name="paste_desktop_address">Coller l\'adresse du bureau</string> <string name="verify_code_with_desktop">Vérifier le code avec le bureau</string> - <string name="scan_qr_code_from_desktop">Scanner le code QR du bureau</string> + <string name="scan_qr_code_from_desktop">Scannez le code QR du bureau</string> <string name="devices">Appareils</string> <string name="v5_4_more_things_descr">- option pour notifier les contacts supprimés. \n- noms de profil avec espaces. @@ -1522,4 +1516,107 @@ <string name="found_desktop">Bureau trouvé</string> <string name="not_compatible">Non compatible !</string> <string name="multicast_discoverable_via_local_network">Accessible via le réseau local</string> + <string name="refresh_qr_code">Rafraîchir</string> + <string name="create_chat_profile">Créer un profil de chat</string> + <string name="no_connected_mobile">Pas de mobile connecté</string> + <string name="disconnect_remote_hosts">Déconnecter les mobiles</string> + <string name="random_port">Aléatoire</string> + <string name="open_port_in_firewall_desc">Afin de permettre à une application mobile de se connecter à votre ordinateur, ouvrez ce port dans votre pare-feu, si vous l\'avez activé</string> + <string name="app_was_crashed">Crash d\'aperçu</string> + <string name="open_port_in_firewall_title">Ouvrir le port de votre pare-feu</string> + <string name="error_showing_content">erreur d\'affichage de contenu</string> + <string name="error_showing_message">erreur d\'affichage de message</string> + <string name="you_can_make_address_visible_via_settings">Vous pouvez le rendre visible à vos contacts SimpleX via Paramètres.</string> + <string name="recent_history_is_not_sent_to_new_members">L\'historique n\'est pas envoyé aux nouveaux membres.</string> + <string name="retry_verb">Réessayer</string> + <string name="camera_not_available">Caméra non disponible</string> + <string name="enable_sending_recent_history">Envoi des 100 derniers messages aux nouveaux membres.</string> + <string name="add_contact_button_to_create_link_or_connect_via_link"><![CDATA[<b>Ajouter un contact</b> : pour créer un nouveau lien d\'invitation ou se connecter via un lien que vous avez reçu.]]></string> + <string name="disable_sending_recent_history">Ne pas envoyer d\'historique aux nouveaux membres.</string> + <string name="or_show_this_qr_code">Ou présenter ce code</string> + <string name="recent_history_is_sent_to_new_members">Les 100 derniers messages sont envoyés aux nouveaux membres.</string> + <string name="code_you_scanned_is_not_simplex_link_qr_code">Le code scanné n\'est pas un code QR de lien SimpleX.</string> + <string name="the_text_you_pasted_is_not_a_link">Le texte collé n\'est pas un lien SimpleX.</string> + <string name="enable_camera_access">Autoriser l\'accès à la caméra</string> + <string name="you_can_view_invitation_link_again">Vous pouvez à nouveau consulter le lien d\'invitation dans les détails de la connexion.</string> + <string name="keep_unused_invitation_question">Conserver l\'invitation inutilisée ?</string> + <string name="share_this_1_time_link">Partager ce lien d\'invitation unique</string> + <string name="create_group_button_to_create_new_group"><![CDATA[<b>Créer un groupe</b> : pour créer un nouveau groupe.]]></string> + <string name="recent_history">Historique visible</string> + <string name="la_app_passcode">Code d\'accès à l\'app</string> + <string name="new_chat">Nouveau chat</string> + <string name="loading_chats">Chargement des discussions…</string> + <string name="creating_link">Création d\'un lien…</string> + <string name="or_scan_qr_code">Ou scanner le code QR</string> + <string name="invalid_qr_code">Code QR invalide</string> + <string name="add_contact_tab">Ajouter le contact</string> + <string name="tap_to_scan">Appuyez pour scanner</string> + <string name="keep_invitation_link">Conserver</string> + <string name="tap_to_paste_link">Appuyez pour coller le lien</string> + <string name="search_or_paste_simplex_link">Rechercher ou coller un lien SimpleX</string> + <string name="chat_is_stopped_you_should_transfer_database">Le chat est arrêté. Si vous avez déjà utilisé cette base de données sur un autre appareil, vous devez la transférer à nouveau avant de démarrer le chat.</string> + <string name="start_chat_question">Lancer le chat ?</string> + <string name="remote_host_error_bad_state"><![CDATA[État médiocre de la connexion au mobile <b>%s</b>.]]></string> + <string name="remote_ctrl_was_disconnected_title">Connexion interrompue</string> + <string name="remote_ctrl_error_bad_state">État médiocre de la connexion avec le bureau</string> + <string name="possible_deadlock_title">Impasse</string> + <string name="remote_ctrl_error_bad_version">La version de l\'ordinateur de bureau n\'est pas prise en charge. Veillez à utiliser la même version sur les deux appareils.</string> + <string name="remote_ctrl_error_disconnected">Le bureau a été déconnecté</string> + <string name="developer_options_section">Options pour les développeurs</string> + <string name="possible_deadlock_desc">Le code prend trop de temps à s\'exécuter : %1$d secondes. Il est probable que l\'application soit figée : %2$s</string> + <string name="agent_internal_error_title">Erreur interne</string> + <string name="remote_host_error_bad_version"><![CDATA[La version du mobile <b>%s</b> n\'est pas prise en charge. Veillez à utiliser la même version sur les deux appareils.]]></string> + <string name="show_internal_errors">Afficher les erreurs internes</string> + <string name="remote_ctrl_disconnected_with_reason">Déconnecté pour la raison suivante : %s</string> + <string name="failed_to_create_user_invalid_title">Nom d\'affichage invalide !</string> + <string name="failed_to_create_user_invalid_desc">Ce nom d\'affichage est invalide. Veuillez choisir un autre nom.</string> + <string name="remote_ctrl_error_timeout">Délai d\'attente dépassé lors de la connexion au bureau</string> + <string name="agent_critical_error_title">Erreur critique</string> + <string name="agent_critical_error_desc">Veuillez le signaler aux développeurs : +\n%s +\n +\nIl est recommandé de redémarrer l\'application.</string> + <string name="agent_internal_error_desc">Veuillez le signaler aux développeurs : +\n%s</string> + <string name="restart_chat_button">Redémarrer le chat</string> + <string name="group_member_status_unknown_short">inconnu</string> + <string name="group_member_status_unknown">statut inconnu</string> + <string name="remote_host_was_disconnected_title">Connexion interrompue</string> + <string name="past_member_vName">Ancien membre %1$s</string> + <string name="possible_slow_function_desc">La fonctions prend trop de temps à s\'exécuter : %1$d secondes : %2$s</string> + <string name="possible_slow_function_title">Fonction lente</string> + <string name="show_slow_api_calls">Afficher les appels d\'API lents</string> + <string name="remote_host_disconnected_from"><![CDATA[Déconnecté du mobile <b>%s</b> en raison de : %s]]></string> + <string name="remote_host_error_busy"><![CDATA[Mobile <b>%s</b> est occupé]]></string> + <string name="remote_host_error_inactive"><![CDATA[Le mobile <b>%s</b> est inactif]]></string> + <string name="remote_host_error_missing"><![CDATA[Mobile <b>%s</b> est manquant]]></string> + <string name="remote_host_error_disconnected"><![CDATA[Le mobile <b>%s</b> a été déconnecté]]></string> + <string name="remote_host_error_timeout"><![CDATA[Délai d\'attente expiré lors de la connexion au mobile <b>%s</b>]]></string> + <string name="remote_ctrl_error_bad_invitation">Le bureau ne possède pas le bon code d\'invitation</string> + <string name="remote_ctrl_error_busy">Le bureau est occupé</string> + <string name="remote_ctrl_error_inactive">Le bureau est inactif</string> + <string name="v5_5_private_notes_descr">Avec les fichiers et les médias chiffrés.</string> + <string name="v5_5_join_group_conversation_descr">Historique récent et bot d\'annuaire amélioré.</string> + <string name="v5_5_simpler_connect_ui_descr">La barre de recherche accepte les liens d\'invitation.</string> + <string name="v5_5_message_delivery_descr">Consommation réduite de la batterie.</string> + <string name="clear_note_folder_warning">Tous les messages seront supprimés - il n\'est pas possible de revenir en arrière !</string> + <string name="v5_5_new_interface_languages">Interface utilisateur en hongrois et en turc</string> + <string name="v5_5_private_notes">Notes privées</string> + <string name="info_row_created_at">Créé à</string> + <string name="error_creating_message">Erreur lors de la création du message</string> + <string name="v5_5_message_delivery">Amélioration de la transmission des messages</string> + <string name="v5_5_join_group_conversation">Participez aux conversations de groupe</string> + <string name="share_text_created_at">Créé à : %s</string> + <string name="error_deleting_note_folder">Erreur lors de la suppression de notes privées</string> + <string name="v5_5_simpler_connect_ui">Collez le lien pour vous connecter !</string> + <string name="note_folder_local_display_name">Notes privées</string> + <string name="profile_update_event_contact_name_changed">le contact %1$s est devenu %2$s</string> + <string name="profile_update_event_member_name_changed">le membre %1$s est devenu %2$s</string> + <string name="profile_update_event_removed_address">suppression de l\'adresse de contact</string> + <string name="profile_update_event_removed_picture">suppression de la photo de profil</string> + <string name="profile_update_event_set_new_address">définir une nouvelle adresse de contact</string> + <string name="profile_update_event_set_new_picture">définir une nouvelle image de profil</string> + <string name="profile_update_event_updated_profile">profil mis à jour</string> + <string name="clear_note_folder_question">Effacer les notes privées ?</string> + <string name="saved_message_title">Message enregistré</string> </resources> \ No newline at end of file diff --git a/apps/multiplatform/common/src/commonMain/resources/MR/hu/strings.xml b/apps/multiplatform/common/src/commonMain/resources/MR/hu/strings.xml index 21a56d7e99..9647e8a406 100644 --- a/apps/multiplatform/common/src/commonMain/resources/MR/hu/strings.xml +++ b/apps/multiplatform/common/src/commonMain/resources/MR/hu/strings.xml @@ -1,15 +1,15 @@ <?xml version="1.0" encoding="utf-8"?> <resources> - <string name="alert_text_decryption_error_n_messages_failed_to_decrypt">%1$d az üzenetek visszafejtése sikertelen</string> - <string name="alert_text_decryption_error_too_many_skipped">%1$d üzenetek kihagyva.</string> - <string name="integrity_msg_skipped">%1$d kihagyott üzenet(ek)</string> - <string name="group_info_section_title_num_members">%1$s TAGOK</string> + <string name="alert_text_decryption_error_n_messages_failed_to_decrypt">%1$d üzenet visszafejtése sikertelen</string> + <string name="alert_text_decryption_error_too_many_skipped">%1$d üzenet kihagyva.</string> + <string name="integrity_msg_skipped">%1$d kihagyott üzenet</string> + <string name="group_info_section_title_num_members">%1$s TAG</string> <string name="chat_item_ttl_month">1 hónap</string> <string name="chat_item_ttl_week">1 hét</string> <string name="v5_3_new_interface_languages">6 új kezelőfelület nyelv</string> <string name="send_disappearing_message_5_minutes">5 perc</string> <string name="send_disappearing_message_1_minute">1 perc</string> - <string name="learn_more_about_address">A SimpleX azonosítóról</string> + <string name="learn_more_about_address">A SimpleX címről</string> <string name="abort_switch_receiving_address_question">Címváltoztatás megszakítása?</string> <string name="abort_switch_receiving_address_confirm">Megszakítás</string> <string name="send_disappearing_message_30_seconds">30 másodperc</string> @@ -19,166 +19,163 @@ <string name="chat_item_ttl_day">1 nap</string> <string name="abort_switch_receiving_address">Címváltoztatás megszakítása</string> <string name="about_simplex">A SimpleX-ről</string> - <string name="color_primary">Kiemelőszín</string> + <string name="color_primary">Kiemelés</string> <string name="callstatus_accepted">elfogadott hívás</string> - <string name="network_enable_socks_info">Kapcsolódás a szerverekhez SOCKS proxy segítségével a %d? porton? A proxyt el kell indítani mielőtt bekapcsolná ezt az opciót.</string> + <string name="network_enable_socks_info">Kapcsolódás a szerverekhez SOCKS proxy segítségével a %d porton? A proxyt el kell indítani mielőtt bekapcsolnád ezt az opciót.</string> <string name="accept_feature">Elfogad</string> <string name="accept_call_on_lock_screen">Elfogad</string> - <string name="above_then_preposition_continuation">felül, majd pedig:</string> + <string name="above_then_preposition_continuation">fentről, utána:</string> <string name="accept_contact_incognito_button">Elfogadás inkognítóban</string> <string name="accept_connection_request__question">Elfogadod a kapcsolatfelvételt?</string> <string name="accept_contact_button">Elfogad</string> <string name="accept">Elfogad</string> - <string name="add_address_to_your_profile">Add hozzá az azonosítót a profilodhoz, így a kapcsolataid megosztatják azt más emberekkel. A profilod változtatásai így frissítésre kerülnek a kapcsolataidnál is!</string> - <string name="color_primary_variant">További kiemelőszín</string> + <string name="add_address_to_your_profile">Add hozzá a címet a profilodhoz, így a kapcsolataid megoszthatják azt más emberekkel. A profilod változtatásai így frissítésre kerülnek a kapcsolataidnál is!</string> + <string name="color_primary_variant">További kiemelés</string> <string name="callstatus_error">hiba a hívásban</string> <string name="v5_4_block_group_members">Csoporttagok blokkolása</string> <string name="la_authenticate">Hitelesítés</string> <string name="empty_chat_profile_is_created">Egy üres chat profil létre lett hozva a megadott névvel és az app normál módon megnyílik.</string> <string name="feature_cancelled_item">megszakítva %s</string> <string name="smp_servers_preset_add">Adj hozzá egyedi szervereket</string> - <string name="calls_prohibited_with_this_contact">Hang-/videóhívások megtiltva.</string> + <string name="calls_prohibited_with_this_contact">A hang- és videóhívások le vannak tiltva.</string> <string name="network_session_mode_entity_description">Külön TCP kapcsolat (és SOCKS bejelentkezési adatok) lesznek használva <b>minden ismerősre és csoport tagra</b> \n<b>Tudnivaló</b>: ha sok ismerősöd van, az akkumulátor- és adat használatod jelentősen megnőhet és néhány kapcsolódási kísérlet sikertelen lehet.</string> <string name="icon_descr_cancel_link_preview">URL link előnézet megszakítása</string> <string name="network_session_mode_user_description"><![CDATA[Külön TCP kapcsolat (és SOCKS bejelentkezési adatok) lesznek használva <b>minden chat profilodra az appban</b>.]]></string> - <string name="both_you_and_your_contact_can_send_disappearing">Mindketten, te és az ismerősöd is küldhettek eltűnő üzeneteket.</string> - <string name="keychain_is_storing_securely">Az Android Keystore-t jelmondat biztonságos tárolására használják - lehetővé teszi az értesítési szolgáltatás működését.</string> - <string name="scan_QR_code_to_connect_to_contact_who_shows_QR_code"><![CDATA[<b>QR-kód beolvasása</b>: kapcsolódás ismerőshöz a megmutatott QR-kódja alapján]]></string> + <string name="both_you_and_your_contact_can_send_disappearing">Mindketten, te is és az ismerősöd is küldhet eltűnő üzeneteket.</string> + <string name="keychain_is_storing_securely">Az Android Keystore-t a jelmondat biztonságos tárolására használják - lehetővé teszi az értesítési szolgáltatás működését.</string> <string name="alert_title_msg_bad_hash">Téves üzenet hash</string> - <string name="cant_delete_user_profile">Felhasználói profil törlése nem lehetséges!</string> <string name="color_background">Háttér</string> <string name="socks_proxy_setting_limitations"><![CDATA[<b>Tudnivaló</b>: az üzenet- és fájl relay szerverek SOCKS proxy által vannak kapcsolatban. A hívások és URL link előnézetek közvetlen kapcsolatot használnak.]]></string> <string name="full_backup">App adatmentés</string> - <string name="database_initialization_error_title">Adatbázis inicializálása nem lehetséges</string> + <string name="database_initialization_error_title">Az adatbázis inicializálása sikertelen</string> <string name="all_your_contacts_will_remain_connected_update_sent">A kapcsolat megmarad az összes Ismerősöddel. Profil változtatások frissítésre kerülnek az ismerőseidnél.</string> <string name="v4_5_transport_isolation_descr">Chat profile (alap beállítás) avagy kapcsolat által (BÉTA).</string> <string name="connect__a_new_random_profile_will_be_shared">Egy új véletlenszerű profil lesz megosztva.</string> - <string name="allow_voice_messages_only_if">Hangüzenetek küldésének engedélyezése kizárólag az esetre ha a másik fél is engedélyezi.</string> - <string name="app_version_code">App build: %s</string> + <string name="allow_voice_messages_only_if">Hangüzenetek küldésének engedélyezése kizárólag abban az esetben, ha a másik fél is engedélyezi.</string> + <string name="app_version_code">Az alkalmazás build száma: %s</string> <string name="audio_video_calls">Hang-/videóhívások</string> <string name="network_settings">Haladó hálózati beállítások</string> - <string name="allow_your_contacts_to_send_voice_messages">Ismerősök küldhetnek hangüzeneteket engedélyezése.</string> + <string name="allow_your_contacts_to_send_voice_messages">Ismerőseid küldhetnek hangüzeneteket.</string> <string name="settings_audio_video_calls">Hang- és videóhívások</string> <string name="v5_3_encrypt_local_files_descr">Az app titkosítja a helyi fájlokat (a videók kivételével).</string> <string name="answer_call">Hívás fogadása</string> - <string name="allow_your_contacts_to_send_disappearing_messages">Ismerősök küldhetnek eltűnő üzeneteket engedélyezve.</string> + <string name="allow_your_contacts_to_send_disappearing_messages">Ismerőseid küldhetnek eltűnő üzeneteket.</string> <string name="connect_plan_already_connecting">Már kapcsolódik!</string> - <string name="cannot_receive_file">Fájl fogadás nem lehetséges</string> + <string name="cannot_receive_file">Nem tud fájlt fogadni</string> <string name="auth_unavailable">Hitelesítés elérhetetlen</string> - <string name="app_version_title">App verzió</string> - <string name="button_add_welcome_message">Üdvözlőszöveg hozzáadása</string> - <string name="snd_conn_event_ratchet_sync_started">titkosítás egyeztetése %s számára…</string> + <string name="app_version_title">Alkalmazás verzió</string> + <string name="button_add_welcome_message">Üdvözlő üzenet hozzáadása</string> + <string name="snd_conn_event_ratchet_sync_started">a(z) %s titkosításának elfogadása…</string> <string name="available_in_v51">" \nElérhető a v5.1-ben"</string> - <string name="both_you_and_your_contacts_can_delete">Mindketten, te és az ismerősöd is visszaállíthatatlanul törölhettek elküldött üzeneteket.</string> - <string name="v5_4_better_groups">Jobb csoportok</string> - <string name="clear_chat_warning">Minden üzenet törlésre kerül - ez visszafordíthatatlan! Az üzenetek csak NÁLAD törlődnek.</string> + <string name="both_you_and_your_contacts_can_delete">Mindketten, te is és az ismerősöd is véglegesen törölhet elküldött üzeneteket. (24 óra)</string> + <string name="v5_4_better_groups">Javított csoportok</string> + <string name="clear_chat_warning">Minden üzenet törlésre kerül - ezt nem lehet visszavonni! Az üzenetek CSAK nálad törlődnek.</string> <string name="icon_descr_call_ended">Hívás befejeződött</string> <string name="settings_section_title_calls">HÍVÁSOK</string> - <string name="rcv_group_and_other_events">és %d egyéb események</string> - <string name="address_section_title">Azonosító</string> + <string name="rcv_group_and_other_events">és %d egyéb esemény</string> + <string name="address_section_title">Cím</string> <string name="connect_plan_already_joining_the_group">Már csatlakozik a csoporthoz!</string> <string name="auto_accept_contact">Automatikus elfogadás</string> - <string name="notifications_mode_service_desc">Háttérszolgáltatás mindig fut - az értesítések azonnal megjelennek, amint üzenetek vannak.</string> - <string name="allow_to_delete_messages">Elküldött üzenetek visszafordíthatatlan törlésének engedélyezése.</string> - <string name="both_you_and_your_contact_can_send_voice">Mindketten, te és az ismerősöd is küldhettek hangüzeneteket.</string> + <string name="notifications_mode_service_desc">A háttérszolgáltatás mindig fut - az értesítések azonnal megjelennek, amint üzenetek vannak.</string> + <string name="allow_to_delete_messages">Elküldött üzenetek végleges törlésének engedélyezése. (24 óra)</string> + <string name="both_you_and_your_contact_can_send_voice">Mindketten, te is és az ismerősöd is küldhet hangüzeneteket.</string> <string name="alert_title_msg_bad_id">Téves üzenet ID</string> - <string name="allow_your_contacts_adding_message_reactions">Üzenet rakciók -emojik- engedélyezése az ismerősei számára.</string> - <string name="allow_to_send_voice">Hangüzenetek küldésének engedélyezése.</string> - <string name="allow_message_reactions_only_if">Üzenet reakciók -emojik- engedélyezése kizárólag az esetre ha a másik fél is engedélyezi.</string> + <string name="allow_your_contacts_adding_message_reactions">Ismerőseid küldhetnek reakciókat az üzenetekre.</string> + <string name="allow_to_send_voice">Hangüzenetek küldése engedélyezve.</string> + <string name="allow_message_reactions_only_if">Üzenet reakciók engedélyezése kizárólag abban az esetben, ha a másik fél is engedélyezi.</string> <string name="back">Vissza</string> - <string name="it_can_disabled_via_settings_notifications_still_shown"><![CDATA[<b>Kikapcsolható a beállításokban</b> – az értesítések továbbra is megjelenítésre kerülnek amíg az app fut.]]></string> - <string name="v4_2_group_links_desc">Adminok létrehozhatnak linkeket csoporthoz való csatlakozáshoz.</string> + <string name="it_can_disabled_via_settings_notifications_still_shown"><![CDATA[<b>Kikapcsolható a beállításokban</b> – az értesítések továbbra is megjelenítésre kerülnek amíg az alkalmazás fut.]]></string> + <string name="v4_2_group_links_desc">Az adminok létrehozhatnak linkeket a csoporthoz való csatlakozáshoz.</string> <string name="call_on_lock_screen">Hívások a lezárási képernyőn:</string> - <string name="conn_event_ratchet_sync_started">titkosítás egyeztetése…</string> - <string name="invite_prohibited">Ismerős meghívása sikertelen!</string> + <string name="conn_event_ratchet_sync_started">titkosítás elfogadása…</string> + <string name="invite_prohibited">Az ismerősök meghívása le van tiltva!</string> <string name="integrity_msg_bad_id">téves üzenet ID</string> <string name="v4_2_auto_accept_contact_requests">Ismerősnek jelölések automatikus elfogadása</string> <string name="impossible_to_recover_passphrase"><![CDATA[<b>Tudnivaló</b>: NEM fogod tudni helyreállítani vagy megváltoztatni a jelmondatot az esetben ha elveszíted.]]></string> <string name="callstatus_calling">hívás…</string> <string name="color_secondary_variant">További másodlagos</string> <string name="smp_servers_add_to_another_device">Hozzáadás másik eszközhöz</string> - <string name="allow_message_reactions">Üzenet reakciók -emojik- engedélyezése.</string> + <string name="allow_message_reactions">Üzenet reakciók engedélyezése.</string> <string name="icon_descr_cancel_file_preview">Fájl előnézet megszakítása</string> <string name="all_group_members_will_remain_connected">Minden csoporttag kapcsolatban marad.</string> <string name="onboarding_notifications_mode_service_desc"><![CDATA[<b>Több akkumulátort használ</b>! Háttérszolgáltatás mindig fut - értesítések megjelennek azonnal, ahogy új üzenetek érkeznek.]]></string> <string name="block_member_confirmation">Blokkolás</string> <string name="group_member_role_admin">admin</string> <string name="icon_descr_cancel_image_preview">Fénykép előnézet megszakítása</string> - <string name="v5_1_self_destruct_passcode_descr">Minden adat törlődik amint bevitelre kerül.</string> - <string name="icon_descr_video_asked_to_receive">Kérte a videó elfogadását</string> + <string name="v5_1_self_destruct_passcode_descr">Minden adat törlődik miután a jelkód bevitelre került.</string> + <string name="icon_descr_video_asked_to_receive">Felkértek a videó fogadására</string> <string name="block_member_button">Tag blokkolása</string> <string name="v5_2_more_things">Néhány további dolog</string> <string name="authentication_cancelled">Hitelesítés megszakítva</string> - <string name="allow_to_send_files">Fájlok és fotók/videók küldésének engedélyezése.</string> - <string name="users_delete_all_chats_deleted">Minden chat illetve az összes üzenet törlésre kerül - ez visszafordíthatatlan!</string> + <string name="allow_to_send_files">A fájlok- és a médiatartalom küldése engedélyezve.</string> + <string name="users_delete_all_chats_deleted">Minden beszélgetés, illetve az összes üzenet törlésre kerül - ezt nem lehet visszavonni!</string> <string name="icon_descr_audio_call">hanghívás</string> - <string name="bold_text">vastagított</string> - <string name="app_passcode_replaced_with_self_destruct">Az app számkód helyettesítésre kerül egy önmegsemmisítő számkóddal.</string> + <string name="bold_text">félkövér</string> + <string name="app_passcode_replaced_with_self_destruct">Az alkalmazás jelkód helyettesítésre kerül egy önmegsemmisítő jelkóddal.</string> <string name="v5_3_new_interface_languages_descr">Arab, bulgár, finn, héber, thai és ukrán - köszönet a felhasználóknak és a Weblate-nek!</string> - <string name="add_new_contact_to_create_one_time_QR_code"><![CDATA[<b>Új ismerős hozzáadása</b>: egyszer használatos QR-kód készítése az ismerős számára.]]></string> - <string name="allow_voice_messages_question">Hangüzenetek engedélyezése?</string> - <string name="always_use_relay">Mindig használt relay szervert</string> + <string name="allow_voice_messages_question">Engedélyezed a hangüzenetek küldését?</string> + <string name="always_use_relay">Mindig használjon relay szervert</string> <string name="chat_preferences_always">mindig</string> <string name="call_already_ended">A hívás már befejeződött!</string> <string name="turn_off_battery_optimization_button">Engedélyez</string> <string name="all_your_contacts_will_remain_connected">A kapcsolat megmarad az összes Ismerősöddel.</string> <string name="icon_descr_cancel_live_message">Élő chat üzenet megszakítása</string> - <string name="allow_irreversible_message_deletion_only_if">Helyreállíthatatlan üzenet törlés engedélyezése kizárólag az esetre ha a másik fél is engedélyezi.</string> + <string name="allow_irreversible_message_deletion_only_if">Üzenet végleges törlésének engedélyezése kizárólag abban az esetben, ha a másik fél is engedélyezi. (24 óra)</string> <string name="v4_6_audio_video_calls">Hang- és videóhívások</string> <string name="integrity_msg_bad_hash">téves üzenet hash</string> <string name="notifications_mode_service">Mindig bekapcsolva</string> <string name="keychain_allows_to_receive_ntfs">Az Android Keystore fogja biztonságosan tárolni a jelmondatot app újraindítás vagy jelmondat változtatás után - lehetővé téve az értesítések fogadását.</string> - <string name="all_app_data_will_be_cleared">Minden app adat törölve.</string> + <string name="all_app_data_will_be_cleared">Minden alkalmazás adat törölve.</string> <string name="onboarding_notifications_mode_off_desc"><![CDATA[<b>Legjobb akkumulátoridő</b>. Kizárólag akkor kapsz értesítéseket amikor fut az app (NINCS háttérszolgáltatás).]]></string> <string name="appearance_settings">Megjelenés</string> <string name="turning_off_service_and_periodic">Akkumulátor optimizáció aktív, a háttérszolgáltatás és a rendszeres új üzenet ellenőrzés kikapcsolva. Újra bekapcsolhatod ezeket a beállításokban.</string> <string name="block_member_question">Tag blokkolása?</string> - <string name="callstatus_ended">hívás befejeződött %1$s</string> + <string name="callstatus_ended">a(z) %1$s hívás befejeződött</string> <string name="onboarding_notifications_mode_periodic_desc"><![CDATA[<b>Jó akkumulátoridő</b>. A háttérszolgáltatás ellenőrzi az új üzeneteket 10 percenként. Hívásokról és fontos üzenetekről maradhatsz le.]]></string> <string name="group_member_role_author">szerző</string> - <string name="allow_your_contacts_irreversibly_delete">Ismerősök visszafordíthatatlanul törölhetnek elküldött üzeneteket engedélyezve.</string> + <string name="allow_your_contacts_irreversibly_delete">Engedélyezed az ismerőseidnek, hogy visszafordíthatatlanul törölhessék az elküldött üzeneteket. (24 óra)</string> <string name="cancel_verb">Megszakítás</string> - <string name="notifications_mode_off_desc">Az app csak akkor tud értesítéseket fogadni amikor fut, héttérszolgáltatás nem kerül elindításra.</string> + <string name="notifications_mode_off_desc">Az alkalmazás csak akkor tud értesítéseket fogadni amikor fut, a héttérszolgáltatás nem kerül elindításra.</string> <string name="v5_1_better_messages">Jobb üzenetek</string> <string name="abort_switch_receiving_address_desc">A cím változtatás megszakításra kerül. A régi fogadó cím marad használatban.</string> <string name="allow_verb">Engedélyez</string> - <string name="bad_desktop_address">Rossz asztal cím</string> - <string name="users_add">Adj hozzá profilt</string> + <string name="bad_desktop_address">Téves számítógép cím</string> + <string name="users_add">Profil hozzáadása</string> <string name="attach">Csatolás</string> - <string name="v5_0_app_passcode">App számkód</string> - <string name="icon_descr_asked_to_receive">Kérte, hogy fogfaja a képet</string> + <string name="v5_0_app_passcode">Alkalmazás jelkód</string> + <string name="icon_descr_asked_to_receive">Felkértek a kép fogadására</string> <string name="use_camera_button">Fényképező</string> <string name="cannot_access_keychain">A Keystore-hoz nem sikerül hozzáférni az adatbázis jelszó elmentése végett</string> <string name="callstatus_in_progress">hívás folyamatban</string> - <string name="auto_accept_images">Fényképek automatiklus elfogadása</string> - <string name="allow_your_contacts_to_call">Hang- és videóhívás engedélyezése az ismerősei számára.</string> - <string name="settings_section_title_icon">APP IKON</string> + <string name="auto_accept_images">Fotók automatikus elfogadása</string> + <string name="allow_your_contacts_to_call">Hang- és videóhívás engedélyezése az ismerőseid számára.</string> + <string name="settings_section_title_icon">ALKALMAZÁS IKON</string> <string name="v4_3_improved_server_configuration_desc">Szerver hozzáadása QR kód befotózásával.</string> - <string name="allow_to_send_disappearing">Eltünő üzenetek küldésének engedélyezése.</string> - <string name="allow_disappearing_messages_only_if">Eltűnő üzenetek engedélyezése kizárólag az esetre ha a másik fél is engedélyezi.</string> + <string name="allow_to_send_disappearing">Eltűnő üzenetek küldése engedélyezve.</string> + <string name="allow_disappearing_messages_only_if">Eltűnő üzenetek engedélyezése kizárólag abban az esetben, ha a másik fél is engedélyezi.</string> <string name="icon_descr_audio_off">Hang kikapcsolva</string> - <string name="allow_direct_messages">Közvetlen üzenetküldés tagok számára engedélyezett.</string> - <string name="settings_section_title_app">APP</string> + <string name="allow_direct_messages">A közvetlen üzenetküldés csak a tagok számára engedélyezett.</string> + <string name="settings_section_title_app">Alkalmazás</string> <string name="icon_descr_call_progress">Hívás folyamatban</string> - <string name="both_you_and_your_contact_can_add_message_reactions">Mindketten, te és az ismerősöd is használhattok üzenet reakciókat (emojik).</string> - <string name="both_you_and_your_contact_can_make_calls">Mindketten, te és az ismerősöd is tudok hívásokat indítani.</string> + <string name="both_you_and_your_contact_can_add_message_reactions">Mindketten, te is és az ismerősöd is használhat üzenet reakciókat (emojik).</string> + <string name="both_you_and_your_contact_can_make_calls">Mindketten, te is és az ismerősöd is tud hívásokat indítani.</string> <string name="la_auth_failed">Hitelesítés sikertelen</string> <string name="block_member_desc">Minden új üzenet %s -tól/től elrejtésre kerül.</string> - <string name="app_version_name">App verzió: v%s</string> - <string name="allow_calls_only_if">Hívások engedélyezése kizárólag az esetre ha a másik fél is engedélyezi.</string> + <string name="app_version_name">Alkalmazás verzió: v%s</string> + <string name="allow_calls_only_if">Hívások engedélyezése kizárólag abban az esetben, ha a másik fél is engedélyezi.</string> <string name="smp_servers_add">Szerver hozzáadása…</string> <string name="icon_descr_audio_on">Hang bekapcsolva</string> <string name="audio_call_no_encryption">hanghívás (nem e2e titkosított)</string> <string name="blocked_item_description">blokkolva</string> <string name="change_database_passphrase_question">Adatbázis jelmondat megváltoztatása?</string> <string name="callstate_connected">kapcsolódva</string> - <string name="la_change_app_passcode">Számkód megváltoztatása</string> - <string name="rcv_group_event_changed_member_role">%s to %s megváltozott szerepköre</string> - <string name="switch_receiving_address">Fogadó szerver cím megváltoztatása</string> + <string name="la_change_app_passcode">Jelkód megváltoztatása</string> + <string name="rcv_group_event_changed_member_role">a szerepkör %s -ról(-ről), %s -ra(-re) változott</string> + <string name="switch_receiving_address">A fogadó szerver címének megváltoztatása</string> <string name="change_verb">Változtatás</string> - <string name="confirm_passcode">Számkód megerősítése</string> + <string name="confirm_passcode">Jelkód megerősítése</string> <string name="confirm_password">Jelszó megerősítése</string> <string name="change_member_role_question">Csoport szerepkör megváltoztatása?</string> <string name="change_lock_mode">Lezárási mód megváltoztatása</string> @@ -186,13 +183,13 @@ <string name="rcv_group_event_member_connected">kapcsolódva</string> <string name="connect_via_link_verb">Kapcsolódás</string> <string name="group_member_status_connected">kapcsolódva</string> - <string name="connected_mobile">Összekapcsolt telefon</string> + <string name="connected_mobile">Csatlakoztatott telefon</string> <string name="server_connected">kapcsolódva</string> <string name="change_role">Szerepkör megváltoztatása</string> <string name="icon_descr_server_status_connected">Kapcsolódva</string> <string name="auth_confirm_credential">Belépési adatok megerősítése</string> - <string name="switch_receiving_address_question">Fogadó szerver cím megváltoztatása</string> - <string name="rcv_conn_event_switch_queue_phase_completed">megváltozott azonosító számodra</string> + <string name="switch_receiving_address_question">Fogadó szerver cím megváltoztatása?</string> + <string name="rcv_conn_event_switch_queue_phase_completed">megváltozott az azonosító számodra</string> <string name="change_self_destruct_mode">Önmegsemmisítő mód megváltoztatása</string> <string name="rcv_group_event_changed_your_role">a szerepköröd megváltoztatva %s-ra(-re)</string> <string name="connect_button">Kapcsolódás</string> @@ -203,13 +200,13 @@ <string name="status_contact_has_e2e_encryption">az ismerősnél az e2e titkosítás elérhető</string> <string name="v5_4_incognito_groups_descr">Csoport létrehozása véletlenszerűen létrehozott profillal.</string> <string name="delete_contact_all_messages_deleted_cannot_undo_warning">Az ismerős és az összes üzenet törlésre kerül - ez visszafordíthatatlan!</string> - <string name="contacts_can_mark_messages_for_deletion">Ismerősök megjelölhetik az üzeneteket törlendőként; de láthatod azokat.</string> - <string name="connect_via_invitation_link">Kapcsolódás egy Egyszer használatos linkkel?</string> + <string name="contacts_can_mark_messages_for_deletion">Ismerősök megjelölhetik az üzeneteket törlendőként; de te láthatod azokat.</string> + <string name="connect_via_invitation_link">Kapcsolódás Egyszer használatos linkkel?</string> <string name="connect_via_link_or_qr">Kapcsolódás egy link / QR-kód által</string> <string name="connection_error_auth">Kapcsolódási hiba (AUTH)</string> <string name="notification_preview_mode_contact">Ismerős neve</string> <string name="connect_via_contact_link">Kapcsolódás ismerős azonosítója által?</string> - <string name="create_address">Azonosító létrehozása</string> + <string name="create_address">Cím létrehozása</string> <string name="copy_verb">Másolás</string> <string name="continue_to_next_step">Folytatás</string> <string name="connect_plan_connect_via_link">Kapcsolódás egy linken keresztül?</string> @@ -219,7 +216,7 @@ <string name="connect_plan_connect_to_yourself">Kapcsolódás saját magához?</string> <string name="copied">Kimásolva a vágólapra</string> <string name="connection_request_sent">Kapcsolódási kérés elküldve!</string> - <string name="connecting_to_desktop">Kapcsolódás az asztalhoz</string> + <string name="connecting_to_desktop">Kapcsolódás az asztali klienshez</string> <string name="network_session_mode_entity">Kapcsolat</string> <string name="correct_name_to">Név helyesbítése erre: %s?</string> <string name="connection_timeout">Kapcsolat időtúllépés</string> @@ -230,9 +227,9 @@ <string name="desktop_connection_terminated">Kapcsolat megszakítva</string> <string name="display_name_connection_established">Kapcsolat létrehozva</string> <string name="status_contact_has_no_e2e_encryption">az ismerősnél az e2e titkosítás nem elérhető</string> - <string name="chat_preferences_contact_allows">Az ismerős engedélyezi</string> + <string name="chat_preferences_contact_allows">Ez az ismerősöd engedélyezi</string> <string name="notification_preview_somebody">Ismerős elrejtve:</string> - <string name="connect_to_desktop">Kapcsolódás az asztalhoz</string> + <string name="connect_to_desktop">Kapcsolódás az asztali klienshez</string> <string name="icon_descr_context">Kontextus ikon</string> <string name="connect_via_link">Kapcsolódás egy linken keresztül</string> <string name="receipts_section_contacts">Ismerősök</string> @@ -242,7 +239,7 @@ \n- kézbesítési igazolások (20 tagig). \n- gyorsabb és stabilabb</string> <string name="contribute">Hozzájárulás</string> - <string name="group_member_status_intro_invitation">kapcsolódás (meghívás bemutatkozásra)</string> + <string name="group_member_status_intro_invitation">csatlakozás (bemutatkozás meghívás)</string> <string name="create_simplex_address">SimpleX azonosító létrehozása</string> <string name="rcv_direct_event_contact_deleted">törölt ismerős</string> <string name="delete_member_message__question">Tag üzenetének törlése?</string> @@ -254,7 +251,7 @@ <string name="create_group_button">Csoport létrehozása</string> <string name="network_session_mode_user">Chat profil</string> <string name="create_another_profile_button">Profil létrehozása</string> - <string name="connected_desktop">Csatlakoztatott asztal</string> + <string name="connected_desktop">Csatlakoztatott számítógép</string> <string name="share_text_deleted_at">Törölve ekkor: %s</string> <string name="info_row_deleted_at">Törölve ekkor</string> <string name="v4_6_chinese_spanish_interface">Kínai és spanyol kezelőfelület.</string> @@ -263,12 +260,12 @@ <string name="theme_dark">Sötét</string> <string name="create_profile">Profil létrehozása</string> <string name="rcv_group_event_group_deleted">törölt csoport</string> - <string name="full_deletion">Törlés mindenkinek</string> + <string name="full_deletion">Törlés mindenkinél</string> <string name="button_create_group_link">Link létrehozása</string> <string name="chat_preferences">Chat beállítások</string> <string name="chat_archive_header">Chat archívum</string> <string name="delete_profile">Profil törlése</string> - <string name="la_current_app_passcode">Jelenlegi Számkód</string> + <string name="la_current_app_passcode">Jelenlegi Jelkód</string> <string name="group_member_status_connecting">kapcsolódás</string> <string name="confirm_new_passphrase">Új jelmondat megerősítése…</string> <string name="group_connection_pending">kapcsolódás…</string> @@ -279,7 +276,7 @@ <string name="maximum_supported_file_size">Jelenleg támogatott legnagyobb fájl méret: %1$s.</string> <string name="smp_server_test_delete_file">Fájl törlése</string> <string name="in_developing_title">Hamarosan!</string> - <string name="snd_conn_event_switch_queue_phase_changing_for_member">azonosító megváltoztatása %s számára…</string> + <string name="snd_conn_event_switch_queue_phase_changing_for_member">azonosító megváltoztatása %s -ra/re…</string> <string name="chat_database_imported">Chat adatbázis importálva</string> <string name="chat_archive_section">CHAT ARCHÍVUM</string> <string name="delete_messages">Üzenetek törlése?</string> @@ -290,10 +287,10 @@ <string name="v5_1_custom_themes_descr">Színsémák személyreszabása és megosztása</string> <string name="delete_chat_profile_question">Chat profil törlése?</string> <string name="create_group">Titkos csoport létrehozása</string> - <string name="connected_to_desktop">Kapcsolódva az asztalhoz</string> + <string name="connected_to_desktop">Csatlakozva a számítógéphez</string> <string name="configure_ICE_servers">ICE sezrverek beállítása</string> <string name="button_delete_group">Csoport törlése</string> - <string name="clear_verification">Chat hitelesításe</string> + <string name="clear_verification">Hitelesítés törlése</string> <string name="group_member_status_creator">szerző</string> <string name="confirm_verb">Megerősítés</string> <string name="for_me_only">Törlés nálam</string> @@ -307,10 +304,10 @@ <string name="snd_conn_event_switch_queue_phase_changing">azonosító megváltoztatása…</string> <string name="display_name_connecting">kapcsolódás…</string> <string name="icon_descr_call_connecting">Hívás kapcsolása</string> - <string name="delete_files_and_media_question">Fájlok illetve fotók/videók törlése?</string> - <string name="group_member_status_complete">befejezve</string> + <string name="delete_files_and_media_question">Biztosan törlöd a fájlokat és a médiatartalmakat?</string> + <string name="group_member_status_complete">befejezett</string> <string name="chat_database_section">CHAT ADATBÁZIS</string> - <string name="change_self_destruct_passcode">Önmegsemmisító számkód megváltoztatása</string> + <string name="change_self_destruct_passcode">Önmegsemmisító jelkód megváltoztatása</string> <string name="smp_server_test_create_queue">Várólista létrehozása</string> <string name="colored_text">színes</string> <string name="callstate_connecting">kapcsolódás…</string> @@ -334,11 +331,10 @@ <string name="smp_server_test_delete_queue">Várólista törlése</string> <string name="button_delete_contact">Ismerős törlése</string> <string name="archive_created_on_ts">Létrehozva: %1$s</string> - <string name="rcv_conn_event_switch_queue_phase_changing">azonosító megváltoztatása…</string> - <string name="connected_to_mobile">Kapcsolódva a mobilhoz</string> + <string name="rcv_conn_event_switch_queue_phase_changing">címek megváltoztatása…</string> + <string name="connected_to_mobile">Csatlakoztatva a mobilhoz</string> <string name="current_passphrase">Jelenlegi jelmondat…</string> <string name="choose_file_title">Fájl választása</string> - <string name="create_one_time_link">Egyszer használatos meghívó link létrehozása</string> <string name="delete_image">Kép törlése</string> <string name="smp_server_test_create_file">Fájl létrehozása</string> <string name="create_secret_group_title">Tikos csoport létrehozása</string> @@ -355,26 +351,26 @@ <string name="clear_chat_question">Chat kiürítése?</string> <string name="database_downgrade">Adatbázis downgrade?</string> <string name="clear_chat_button">Chat kiürítése</string> - <string name="database_passphrase_will_be_updated">Adatbázis titkosítási jelmondat meg lesz változtatva.</string> + <string name="database_passphrase_will_be_updated">Adatbázis titkosítási jelmondat frissítve lesz.</string> <string name="multicast_connect_automatically">Kapcsolódás automatikusan</string> <string name="database_error">Adatbázis hiba</string> <string name="database_encryption_will_be_updated_in_settings">Adatbázis titkosítási jelmondat frissül és eltárolásra kerül a beállításokban.</string> <string name="info_row_database_id">Adatbázis ID</string> <string name="share_text_database_id">Adatbázis ID: %d</string> - <string name="developer_options">Adatbázis azonosítók és \"Transport Isolation\" opciók.</string> + <string name="developer_options">Adatbázis azonosítók és Átviteli izolációs beállítások.</string> <string name="database_encryption_will_be_updated">Az adatbázis titkosítás jelmondata megváltoztatásra és elmentésre kerül a Keystore-ban.</string> <string name="database_will_be_encrypted_and_passphrase_stored_in_settings">Az adatbázis titkosításra kerül és a jelmondat eltárolásra a beállításokban.</string> <string name="smp_servers_delete_server">Szerver törlése</string> <string name="auth_device_authentication_is_disabled_turning_off">Eszközhitelesítés kikapcsolva. SimpleX zár kikapcsolása.</string> <string name="no_call_on_lock_screen">Letiltás</string> - <string name="receipts_groups_disable_for_all">Letiltás minden csoportnak</string> - <string name="receipts_groups_enable_for_all">Engedélyezve minden csoportnak</string> + <string name="receipts_groups_disable_for_all">Letiltás minden csoport számára</string> + <string name="receipts_groups_enable_for_all">Minden csoportnak engedélyezve</string> <string name="feature_enabled_for_contact">engedélyezve az ismerősnek</string> - <string name="disappearing_messages_are_prohibited">Eltűnő üzenetek tiltottak ebben a csoportban.</string> - <string name="delete_address">Azonosító törlés</string> + <string name="disappearing_messages_are_prohibited">Az eltűnő üzenetek küldése le van tiltva ebben a csoportban.</string> + <string name="delete_address">Azonosító törlése</string> <string name="ttl_week">%d hét</string> - <string name="desktop_address">PC címe</string> - <string name="ttl_s">%ds</string> + <string name="desktop_address">Számítógép azonosítója</string> + <string name="ttl_s">%dmp</string> <string name="delivery_receipts_title">Kézbesítési izagolások!</string> <string name="auth_device_authentication_is_not_enabled_you_can_turn_on_in_settings_once_enabled">Eszközhitelesítés nincs bekapcsolva. Bekapcsolhatod a SimpleX zárat a Beállításokon keresztük, miután bekapcsoltad az eszközhitelesítést.</string> <string name="decryption_error">Titkosítás visszafejtési hiba</string> @@ -384,11 +380,11 @@ <string name="ttl_hours">%d óra</string> <string name="ttl_months">%d hónap</string> <string name="delete_address__question">Azonosító törlése?</string> - <string name="receipts_contacts_title_disable">Igazolások letiltása?</string> + <string name="receipts_contacts_title_disable">Letiltod az üzenet kézbesítési jelentéseket?</string> <string name="passphrase_is_different">Az adatbázis jelmondat eltérő a Keystore-ba elmentettől.</string> <string name="direct_messages">Közvetlen üzenetek</string> <string name="icon_descr_email">E-mail</string> - <string name="receipts_contacts_disable_for_all">Letiltás mindenkinek</string> + <string name="receipts_contacts_disable_for_all">Letiltás mindenki számára</string> <string name="settings_developer_tools">Fejlesztői eszközök</string> <string name="database_passphrase">Adatbázis jelmondat</string> <string name="ttl_days">%d napok</string> @@ -398,7 +394,7 @@ <string name="ttl_w">%dhét</string> <string name="discover_on_network">Felfedezés helyi hálózatomn keresztül</string> <string name="v5_3_discover_join_groups">Helyi csoportok felfedezése és csatolakozás</string> - <string name="moderated_items_description">%d üzenet moderálva %s által</string> + <string name="moderated_items_description">%1$d üzenet moderálva %2$s által</string> <string name="disappearing_message">Eltűnő üzenet</string> <string name="dont_create_address">Ne hozz létre azonosítót</string> <string name="dont_show_again">Ne mutasd ismét</string> @@ -407,7 +403,7 @@ <string name="settings_section_title_device">ESZKÖZ</string> <string name="encrypted_video_call">e2e titkosított videóhívás</string> <string name="conn_level_desc_direct">közvetlen</string> - <string name="desktop_device">PC</string> + <string name="desktop_device">Számítógép</string> <string name="la_minutes">%d perc</string> <string name="num_contacts_selected">%d ismerős(-ök) kiválasztva</string> <string name="enable_receipts_all">Engedélyez</string> @@ -415,13 +411,13 @@ <string name="direct_messages_are_prohibited_in_chat">A közvetlen üzenetek tagok között titltottak ebben a csoportban.</string> <string name="ttl_min">%d perc</string> <string name="set_password_to_export_desc">Az adatbázis egy véletlenszerű jelmondattal van titkosítva. Kérlek cseréld le exportálás előtt!</string> - <string name="receipts_groups_title_disable">Igazolások letiltása csoportoknak?</string> + <string name="receipts_groups_title_disable">Letiltod az üzenet kézbesítés jelentéseket a csoportok számára?</string> <string name="custom_time_unit_days">nap</string> <string name="ttl_day">%d nap</string> <string name="delete_chat_archive_question">Chat archív törlése?</string> <string name="failed_to_create_user_duplicate_title">Duplikálódott megjelenítési név!</string> - <string name="receipts_contacts_disable_keep_overrides">Letiltás(felülírások megtartásával)</string> - <string name="database_upgrade">"Adatbázis upgrade"</string> + <string name="receipts_contacts_disable_keep_overrides">Letiltás (felülírások megtartásával)</string> + <string name="database_upgrade">Adatbázis fejlesztése</string> <string name="blocked_items_description">%d üzenet blokkolva</string> <string name="info_row_disappears_at">Eltűnik ekkor</string> <string name="ttl_weeks">%d hét</string> @@ -435,29 +431,29 @@ <string name="database_will_be_encrypted">Az adatbázis titkosításra kerül.</string> <string name="database_passphrase_and_export">Adatbázis jelmondat és exportálás</string> <string name="database_will_be_encrypted_and_passphrase_stored">Az adatbázis titkosításra kerül és a jelmondat eltárolásra a Keystore-ban.</string> - <string name="enable_automatic_deletion_question">Automatikus üzenet törlés engedélyezve?</string> + <string name="enable_automatic_deletion_question">Engedélyezed az automatikus üzenet törlést?</string> <string name="delete_contact_menu_action">Törlés</string> - <string name="mtr_error_no_down_migration">az adatbázis verzió újabb, mint az app, de nincs lefelé migráció eddig: %s</string> + <string name="mtr_error_no_down_migration">az adatbázis verzió újabb, mint az alkalmazás, de nincs lefelé migráció eddig: %s</string> <string name="simplex_link_mode_description">Leírás</string> <string name="ttl_hour">%d óra</string> <string name="ttl_m">%dp</string> <string name="disconnect_remote_host">Szétkapcsolás</string> <string name="edit_verb">Szerkesztés</string> - <string name="receipts_groups_disable_keep_overrides">Letiltás(csoport felülírások megtartásával)</string> + <string name="receipts_groups_disable_keep_overrides">Letiltás (csoport felülírások megtartásával)</string> <string name="rcv_group_events_count">%d csoportesemény</string> <string name="ttl_month">%d hónap</string> <string name="button_edit_group_profile">Csoport profil szerkesztése</string> <string name="encrypted_audio_call">e2e titkosított hanghívás</string> - <string name="ttl_sec">%d s</string> + <string name="ttl_sec">%d mp</string> <string name="decentralized">Decentralizált</string> <string name="image_decoding_exception_title">Dekódolási hiba</string> <string name="edit_image">Kép szerkesztése</string> - <string name="disable_notifications_button">Értesítéásek letiltása</string> + <string name="disable_notifications_button">Értesítések letiltása</string> <string name="devices">Eszközök</string> <string name="multicast_discoverable_via_local_network">Látható helyi hálózaton</string> <string name="dont_enable_receipts">Ne engedélyezd</string> <string name="delete_archive">Archívum törlése</string> - <string name="disappearing_prohibited_in_this_chat">Eltűnő üzenetek tiltottak ebben a chatben.</string> + <string name="disappearing_prohibited_in_this_chat">Az eltűnő üzenetek le vannak tiltva ebben a csevegésben.</string> <string name="chat_preferences_default">alap (%s)</string> <string name="integrity_msg_duplicate">duplikálódott üzenet</string> <string name="disconnect_desktop_question">Számítógép leválasztása?</string> @@ -465,7 +461,1170 @@ <string name="delivery">Kézbesítés</string> <string name="total_files_count_and_size">%d fájl %s összméretben</string> <string name="database_passphrase_is_required">Adatbázis jelmondat szükséges chat megnyitásához.</string> - <string name="ttl_d">%dn</string> - <string name="receipts_contacts_enable_for_all">Engedélyeve mindenki számára</string> + <string name="ttl_d">%dnap</string> + <string name="receipts_contacts_enable_for_all">Mindenki számára engedélyezve</string> <string name="delivery_receipts_are_disabled">Kézbesítési izagolások kikapcsolva!</string> + <string name="expand_verb">Lenyit</string> + <string name="error_sending_message">Hiba az üzenet küldésekor</string> + <string name="la_enter_app_passcode">Add Meg A Jelkódot</string> + <string name="for_everybody">Mindenkinek</string> + <string name="encryption_renegotiation_error">Titkosítás újra egyeztetési hiba</string> + <string name="error_encrypting_database">Hiba az adatbázis titkosításakor</string> + <string name="error_deleting_group">Hiba a csoport törlésekor</string> + <string name="exit_without_saving">Kilépés mentés nélkül</string> + <string name="v5_3_encrypt_local_files">Tárolt fájlok és médiatartalmak titkosítása</string> + <string name="error_setting_address">Hiba az azonosító beállításakor</string> + <string name="group_invitation_expired">A csoport meghívó lejárt</string> + <string name="error_saving_ICE_servers">Hiba az ICE szerverek elmentésekor</string> + <string name="error_alert_title">Hiba</string> + <string name="icon_descr_server_status_error">Hiba</string> + <string name="error_loading_xftp_servers">Hiba az XFTP szerverek betöltésekor</string> + <string name="error_loading_smp_servers">Hiba az SMP szerverek betöltésekor</string> + <string name="error_setting_network_config">Hiba a hálózat konfigurációjának frissítésekor</string> + <string name="network_option_enable_tcp_keep_alive">TCP életbentartás engedélyezése</string> + <string name="icon_descr_flip_camera">Kamera megfordítása</string> + <string name="email_invite_body">Szia! +\nCsatlakozz hozzám SimpleX Chaten: %s</string> + <string name="display_name_cannot_contain_whitespace">A megjelenített név nem tartalmazhat szóközöket.</string> + <string name="info_row_group">Csoport</string> + <string name="enter_welcome_message_optional">Írd be az üdvözlő üzenetet… (opcionális)</string> + <string name="error_exporting_chat_database">Hiba a chat adatbázis exportálásakor</string> + <string name="error_saving_file">Hiba a fájl elmentésekor</string> + <string name="encrypt_local_files">Helyi fájlok titkosítása</string> + <string name="snd_conn_event_ratchet_sync_agreed">titkosítás egyeztetve %s számára</string> + <string name="marked_deleted_items_description">%d üzenet megjelölve törlésre</string> + <string name="conn_event_ratchet_sync_allowed">titkosítás újra egyeztetése engedélyezve</string> + <string name="enable_self_destruct">Önmegsemmisítés engedélyezése</string> + <string name="v5_2_favourites_filter_descr">Olvasatlan és kedvenc chatekre szűrés.</string> + <string name="failed_to_parse_chats_title">Chatek betöltése sikertelen</string> + <string name="connect_plan_group_already_exists">A csoport már létezik!</string> + <string name="v4_4_french_interface">Francia kezelőfelület</string> + <string name="v4_2_group_links">Csoport linkek</string> + <string name="v5_1_message_reactions_descr">Végre, megvannak! 🚀</string> + <string name="error_starting_chat">Hiba a chat elindításakor</string> + <string name="group_profile_is_stored_on_members_devices">A csoport profil a tagok eszközein tárolódik, nem a szervereken.</string> + <string name="enter_passphrase">Add meg a jelmondatot…</string> + <string name="error_updating_user_privacy">Hiba a felhasználói beállítások frissítésekor</string> + <string name="encrypt_database">Titkosít</string> + <string name="alert_title_no_group">Csoport nem található!</string> + <string name="error_saving_smp_servers">Hiba az SMP szerverek elmentésekor</string> + <string name="downgrade_and_open_chat">Downgrade és chat megnyitása</string> + <string name="icon_descr_group_inactive">A csoport inaktív</string> + <string name="v5_0_large_files_support_descr">Gyors és nincs várakozás a küldő online állapotára!</string> + <string name="error_joining_group">Hiba a csoporthoz csatlakozáskor</string> + <string name="favorite_chat">Kedvenc</string> + <string name="v4_6_group_moderation">Csoport moderáció</string> + <string name="choose_file">Fájl</string> + <string name="group_link">Csoport link</string> + <string name="snd_conn_event_ratchet_sync_required">titkosítás újra egyeztetés szükséges %s számára</string> + <string name="failed_to_active_user_title">Hiba a profil váltásakor!</string> + <string name="settings_experimental_features">Kísérleti funkciók</string> + <string name="receipts_contacts_enable_keep_overrides">Engedélyezés (felülírások megtartásával)</string> + <string name="enter_correct_passphrase">Helyes jelmondat bevitele.</string> + <string name="delete_group_for_self_cannot_undo_warning">A csoport törlésre kerül számodra -ez visszafordíthatatlan!</string> + <string name="encrypt_database_question">Adatbázis titkosítása?</string> + <string name="allow_accepting_calls_from_lock_screen">A zárolási képernyőn megjelenő hívások engedélyezése a Beállításokban.</string> + <string name="conn_event_ratchet_sync_agreed">titkosítás egyeztetve</string> + <string name="receipts_contacts_title_enable">Engedélyezed az üzenet kézbesítési jelentéseket?</string> + <string name="error_saving_group_profile">Hiba a csoport profil elmentésekor</string> + <string name="server_error">hiba</string> + <string name="revoke_file__message">A fájl törölve lesz a szerverekről.</string> + <string name="v5_2_disappear_one_message_descr">Akkor is, ha le van tiltva a beszélgetésben.</string> + <string name="v5_4_better_groups_descr">Gyorsabb csatlakozás és megbízhatóbb üzenet kézbesítés.</string> + <string name="enable_lock">Zár engedélyezése</string> + <string name="settings_section_title_help">SEGÍTSÉG</string> + <string name="group_is_decentralized">Teljesen decentralizált - kizárólag tagok számára látható.</string> + <string name="file_with_path">Fájl: %s</string> + <string name="icon_descr_hang_up">Hívás befejezése</string> + <string name="error_deleting_link_for_group">Hiba a csoport linkjének törlésekor</string> + <string name="file_saved">Fájl elmentve</string> + <string name="fix_connection_question">Kapcsolat javítása?</string> + <string name="files_and_media">Fájlok és médiatartalom</string> + <string name="section_title_for_console">A KONZOL SZÁMÁRA</string> + <string name="alert_text_encryption_renegotiation_failed">Titkosítás újra egyeztetés sikertelen.</string> + <string name="error_deleting_user">Hiba a felhasználói profil törlésekor</string> + <string name="fix_connection_not_supported_by_group_member">A javítás nem támogatott a csoporttag által</string> + <string name="enter_welcome_message">Írd be az üdvözlő üzenetet…</string> + <string name="encrypted_database">Titkosított adatbázis</string> + <string name="enter_password_to_show">Add meg a jelszót a keresőben</string> + <string name="file_will_be_received_when_contact_completes_uploading">A fájl megérkezik amint az ismerősöd befejezi a feltöltését.</string> + <string name="smp_server_test_download_file">Fájl letöltése</string> + <string name="failed_to_parse_chat_title">Chat betöltése sikertelen</string> + <string name="smp_servers_enter_manually">Szerver megadása kézileg</string> + <string name="file_will_be_received_when_contact_is_online">A fájl megérkezik amint az ismerősöd online lesz, kélrlek várj vagy nézz vissza később!</string> + <string name="error_creating_link_for_group">Hiba a csoport linkjének létrehozásakor</string> + <string name="from_gallery_button">A Galériából</string> + <string name="receipts_groups_enable_keep_overrides">Engedélyezés (csoport felülírások megtartásával)</string> + <string name="error_deleting_contact">Hiba az ismerős törlésekor</string> + <string name="group_members_can_delete">A csoporttagok visszafordíthatatlanul törölhetnek elküldött üzeneteket. (24 óra)</string> + <string name="error_changing_role">Hiba a szerepkör megváltoztatásakor</string> + <string name="fix_connection_confirm">Javítás</string> + <string name="group_members_can_send_disappearing">A csoporttagok küldhetnek eltűnő üzeneteket.</string> + <string name="fix_connection">Kapcsolat javítása</string> + <string name="failed_to_create_user_title">Hiba a profil létrehozásakor!</string> + <string name="error_adding_members">Hiba a tag(-ok) hozzáadásakor</string> + <string name="icon_descr_file">Fájl</string> + <string name="group_members_can_send_files">A csoporttagok küldhetnek fájlokat és médiatartalmakat.</string> + <string name="delete_after">Törlés miután</string> + <string name="error_changing_message_deletion">Hiba a beállítás megváltoztatásakor</string> + <string name="error_updating_link_for_group">Hiba a csoport link frissítésekor</string> + <string name="group_member_status_group_deleted">a csoport törölve</string> + <string name="snd_group_event_group_profile_updated">csoport profil frissítve</string> + <string name="error_deleting_pending_contact_connection">Hiba a függőben lévő parner kapcsolatának törlésekor</string> + <string name="error_importing_database">Hiba a chat adatbázis importálásakor</string> + <string name="error_enabling_delivery_receipts">Hiba a kézbesítési jelentések engedélyezésekor!</string> + <string name="error_saving_xftp_servers">Hiba az XFTP szerverek mentésekor</string> + <string name="group_members_can_send_dms">A csoporttagok küldhetnek közvetlen üzeneteket.</string> + <string name="error_removing_member">Hiba a tag eltávolításakor</string> + <string name="callstate_ended">befejeződött</string> + <string name="v4_6_group_welcome_message">A csoport üdvözlő üzenete</string> + <string name="group_display_name_field">Csoport neve:</string> + <string name="error_sending_message_contact_invitation">Hiba a meghívó küldésekor</string> + <string name="display_name">Add meg a nevedet:</string> + <string name="error_saving_user_password">Hiba a felhasználó jelszavának mentésekor</string> + <string name="export_theme">Színséma exportálása</string> + <string name="enter_this_device_name">Add meg ennek az eszköznek a nevét…</string> + <string name="error">Hiba</string> + <string name="alert_message_group_invitation_expired">A csoport meghívó már nem érvényes, el lett távolítva a küldője által.</string> + <string name="group_full_name_field">A csoport teljes neve:</string> + <string name="icon_descr_help">segítség</string> + <string name="enabled_self_destruct_passcode">Önmegsemmisítő jelkód engedélyezése</string> + <string name="settings_section_title_experimenta">KÍSÉRLETI</string> + <string name="error_aborting_address_change">Hiba az azonosító megváltoztatásának megszakításakor</string> + <string name="error_receiving_file">Hiba a fájl fogadásakor</string> + <string name="conn_event_ratchet_sync_ok">titkosítás rendben</string> + <string name="error_deleting_contact_request">Hiba az ismerős kérés törlésekor</string> + <string name="receipts_groups_title_enable">Engedélyezed a csoportok számára az üzenet kézbesítési jelentéseket?</string> + <string name="fix_connection_not_supported_by_contact">A javítás nem támogatott az ismerős által</string> + <string name="file_not_found">Fájl nem található</string> + <string name="smp_server_test_disconnect">Kapcsolat bontása</string> + <string name="group_members_can_add_message_reactions">A csoporttagok reagálhatnak emocikonokkal az üzenetekre.</string> + <string name="export_database">Adatbázis exportálása</string> + <string name="full_name__field">Teljes név:</string> + <string name="v4_6_reduced_battery_usage">Tovább csökkentett akkumulátor használat</string> + <string name="error_stopping_chat">Hiba a chat megállításakor</string> + <string name="snd_conn_event_ratchet_sync_ok">titkosítás rendben %s számára</string> + <string name="delete_group_for_all_members_cannot_undo_warning">Csoport törlésre kerül minen tag számára - ez visszafordíthatatlan!</string> + <string name="v5_2_fix_encryption_descr">Titkosítás javítása az adatmentések helyreállítása után.</string> + <string name="error_deleting_database">Hiba a chat adatbázis törlésekor</string> + <string name="simplex_link_mode_full">Teljes link</string> + <string name="error_changing_address">Hiba az azonosító megváltoztatásakor</string> + <string name="group_members_can_send_voice">A csoporttagok küldhetnek hangüzeneteket.</string> + <string name="group_preferences">Csoport beállítások</string> + <string name="error_with_info">Hiba: %s</string> + <string name="v4_4_disappearing_messages">Eltűnő üzenetek</string> + <string name="auth_enable_simplex_lock">SimpleX Zár engedélyezése</string> + <string name="error_synchronizing_connection">Hiba a kapcsolat szinkronizációjakor</string> + <string name="error_creating_address">Hiba az azonosító létrehozásakor</string> + <string name="feature_enabled">engedélyezve</string> + <string name="error_loading_details">Hiba a részletek betöltésekor</string> + <string name="error_accepting_contact_request">Hiba az ismerős kérés elfogadása</string> + <string name="snd_conn_event_ratchet_sync_allowed">%s ismerősöddel való titkosítás újra egyeztetése engedélyezve</string> + <string name="conn_event_ratchet_sync_required">titkosítás újra egyeztetés szükséges</string> + <string name="v4_6_hidden_chat_profiles">Rejtett chat profilok</string> + <string name="files_and_media_section">Fájlok és média</string> + <string name="image_saved">Fotók elmentve a fotóalbumba</string> + <string name="hide_notification">Elrejt</string> + <string name="la_immediately">Azonnal</string> + <string name="files_and_media_prohibited">A fájlok- és a médiatartalom küldése le van tiltva!</string> + <string name="hide_profile">Profil elrejtése</string> + <string name="how_to_use_your_servers">Hogyan használd a szervereidet</string> + <string name="v5_2_favourites_filter">Találd meg a chat üzeneteket gyorsabban</string> + <string name="import_theme">Színséma importálása</string> + <string name="import_theme_error">Hiba a színséma importálásakor</string> + <string name="notification_display_mode_hidden_desc">Ismerős és üzenet elrejtése</string> + <string name="incompatible_database_version">Nem kompatibilis adatbázis verzió</string> + <string name="how_simplex_works">Hogyan működik a SimpleX</string> + <string name="desktop_incompatible_version">Nem kompatibilis verzió</string> + <string name="user_hide">Elrejt</string> + <string name="incoming_video_call">Bejövő videóhívás</string> + <string name="incorrect_passcode">Téves jelkód</string> + <string name="onboarding_notifications_mode_service">Azonnali</string> + <string name="v5_4_incognito_groups">Inkognitó csoportok</string> + <string name="how_to">Hogyan</string> + <string name="hide_verb">Elrejt</string> + <string name="gallery_image_button">Kép</string> + <string name="v4_3_improved_privacy_and_security">Fejlesztett adatvédelm és biztonság</string> + <string name="ignore">Figyelmen kívül hagyás</string> + <string name="icon_descr_image_snd_complete">Kép elküldve</string> + <string name="notification_preview_mode_hidden">Rejtett</string> + <string name="host_verb">Házigazda</string> + <string name="initial_member_role">Kezdeti szerepkör</string> + <string name="invalid_chat">Érvénytelen chat</string> + <string name="custom_time_unit_hours">órák</string> + <string name="incognito">Inkognitó</string> + <string name="how_to_use_simplex_chat">Hogyan használd</string> + <string name="v4_3_improved_privacy_and_security_desc">App képernyőjének elrejtése a gyakran használt appok között.</string> + <string name="v4_3_improved_server_configuration">Javított szerver konfiguráció</string> + <string name="edit_history">Történet</string> + <string name="hidden_profile_password">Rejtett profil jelszó</string> + <string name="import_database">Adatbázis importálása</string> + <string name="import_database_confirmation">Importálás</string> + <string name="icon_descr_instant_notifications">Azonnali értesítések</string> + <string name="settings_section_title_incognito">Inkognitó mód</string> + <string name="import_database_question">Chat adatbázis importálása?</string> + <string name="service_notifications_disabled">Azonnali értesítések kikapcsolva!</string> + <string name="service_notifications">Azonnali értesítések!</string> + <string name="image_descr">Kép</string> + <string name="files_are_prohibited_in_group">A fájlok- és a médiatartalom küldése le van tiltva ebben a csoportban.</string> + <string name="how_it_works">Hogyan működik</string> + <string name="hide_dev_options">Elrejt:</string> + <string name="error_creating_member_contact">Hiba az ismerősöddel való kapcsolat létrehozásában</string> + <string name="enter_one_ICE_server_per_line">ICE-kiszolgálók (soronként egy)</string> + <string name="if_you_cannot_meet_in_person_scan_QR_in_video_call_or_ask_for_invitation_link"><![CDATA[Ha nem tudtok személyesen találkozni, akkor a videohívásban <b>kiszkennelheted a QR-kódot</b>, vagy a pertnered megoszthat egy meghívó linket.]]></string> + <string name="if_you_enter_passcode_data_removed">Ha az alkalmazás megnyitásakor megadod ezt a jelkódot, az alkalmazás minden adata véglegesen törlődik!</string> + <string name="if_you_cant_meet_in_person">Ha nem tudtok személyesen találkozni, mutassátok meg a QR-kódot egy videohívás során, vagy osszátok meg egymással a linket.</string> + <string name="if_you_cannot_meet_in_person_show_QR_in_video_call_or_via_another_channel"><![CDATA[Ha nem tudtok személyesen találkozni, <b>mutassátok meg a QR-kódot a videohívásban</b>, vagy osszátok meg egymással a linket.]]></string> + <string name="network_disable_socks_info">Ha megerősíted, az üzenetküldő szerverek láthatják az IP-címedet és a szolgáltatódat, vagyis azt, hogy mely szerverekhez csatlakozol.</string> + <string name="image_will_be_received_when_contact_completes_uploading">A kép akkor érkezik meg, amikor az ismerősöd befejezi a feltöltést.</string> + <string name="desktop_scan_QR_code_from_app_via_scan_QR_code"><![CDATA[💻 asztali számítógép: a megjelenített QR-kód beolvasása az alkalmazásból, a <b>QR kód beolvasásával</b>]]></string> + <string name="if_you_received_simplex_invitation_link_you_can_open_in_browser">Ha kaptál egy SimpleX Chat meghívó linket, akkor megnyithatod azt a böngészőben:</string> + <string name="if_you_enter_self_destruct_code">Ha az alkalmazás megnyitásakor megadod az önmegsemmisítő jelkódot:</string> + <string name="found_desktop">Megtalált asztali számítógép</string> + <string name="desktop_devices">Számítógépek</string> + <string name="how_to_use_markdown">Hogyan használjuk a markdown-t</string> + <string name="create_chat_profile">Csevegő profil létrehozása</string> + <string name="immune_to_spam_and_abuse">Spam és visszaélések elleni védelem</string> + <string name="disconnect_remote_hosts">Mobilok leválasztása</string> + <string name="v4_5_multiple_chat_profiles_descr">Különböző nevek, avatarok és átviteli izoláció.</string> + <string name="if_you_choose_to_reject_the_sender_will_not_be_notified">Ha úgy döntesz, hogy elutasítod a küldő NEM kap értesítést.</string> + <string name="icon_descr_expand_role">Szerepkör kibővítése</string> + <string name="image_will_be_received_when_contact_is_online">A kép akkor érkezik meg, amikor az ismerősöd elérhető lesz, kérlek várj vagy nézd meg később!</string> + <string name="group_member_status_invited">meghívott</string> + <string name="invalid_connection_link">Érvénytelen kapcsolati hivatkozás</string> + <string name="mute_chat">Elnémít</string> + <string name="no_details">nincsenek részletek</string> + <string name="icon_descr_call_missed">Nem fogadott hívás</string> + <string name="theme_light">Világos</string> + <string name="delete_message_cannot_be_undone_warning">Az üzenet törlésre kerül - ezt nem lehet visszafordítani!</string> + <string name="markdown_help">Markdown segítség</string> + <string name="notification_preview_new_message">új üzenet</string> + <string name="old_database_archive">Régi adatbázis archívum</string> + <string name="network_settings_title">Hálózati beállítások</string> + <string name="no_info_on_delivery">Nincs kézbesítési információ</string> + <string name="moderated_description">moderált</string> + <string name="member_will_be_removed_from_group_cannot_be_undone">A tag eltávolítása a csoportból - ezt nem lehet visszafordítani!</string> + <string name="ensure_xftp_server_address_are_correct_format_and_unique">Győződj meg róla, hogy az XFTP-kiszolgáló címei megfelelő formátumúak, sorszeparáltak és nem duplikáltak.</string> + <string name="no_contacts_selected">Nincsenek ismerősök kiválasztva</string> + <string name="no_received_app_files">Nincsenek fogadott vagy küldött fájlok</string> + <string name="mobile_tap_open_in_mobile_app_then_tap_connect_in_app"><![CDATA[📱 mobil: koppints a <b>Megnyitás mobil alkalmazásban</b>, majd koppints a <b>Csatlakozás</b> gombra az alkalmazásban.]]></string> + <string name="markdown_in_messages">Markdown az üzenetekben</string> + <string name="group_invitation_item_description">meghívás a %1$s csoportba</string> + <string name="lock_mode">Lezárás mód</string> + <string name="new_mobile_device">Új mobil eszköz</string> + <string name="v5_2_fix_encryption">Kapcsolatok megtartása</string> + <string name="button_add_members">Tagok meghívása</string> + <string name="message_reactions">Üzenet reakciók</string> + <string name="only_one_device_can_work_at_the_same_time">Egyszerre csak egy eszköz működhet</string> + <string name="connect_plan_join_your_group">Csatlakozol a csoportodhoz?</string> + <string name="large_file">Nagy fájl!</string> + <string name="info_row_local_name">Helyi név</string> + <string name="network_and_servers">Hálózat és szerverek</string> + <string name="settings_notification_preview_title">Értesítés előnézet</string> + <string name="v5_4_link_mobile_desktop">Társítsd össze a mobil és az asztali alkalmazásokat! 🔗!</string> + <string name="conn_level_desc_indirect">közvetett (%1$s)</string> + <string name="v4_6_reduced_battery_usage_descr">Hamarosan további fejlesztések érkeznek!</string> + <string name="message_reactions_prohibited_in_this_chat">Az üzenetreakciók ebben a csevegésben tilosak.</string> + <string name="incorrect_code">Helytelen biztonsági kód!</string> + <string name="alert_text_fragment_encryption_out_of_sync_old_database">Ez akkor fordulhat elő, ha Te vagy az ismerősöd a régi adatbázis biztonsági másolatát használta.</string> + <string name="v5_3_new_desktop_app">Új asztali alkalmazás!</string> + <string name="v4_6_group_moderation_descr">Most már az adminok is: +\n- törölhetik a tagok üzeneteit. +\n- letilthatnak tagokat (\"megfigyelő\" szerepkör)</string> + <string name="rcv_group_event_member_added">%1$s meghívott</string> + <string name="message_reactions_are_prohibited">Az üzenetreakciók ebben a csoportban tilosak.</string> + <string name="network_use_onion_hosts_no">Nem</string> + <string name="item_info_no_text">nincs szöveg</string> + <string name="member_info_section_title_member">TAG</string> + <string name="onboarding_notifications_mode_subtitle">Ez később a beállításokon keresztül módosítható.</string> + <string name="new_member_role">Új tag szerepköre</string> + <string name="la_mode_off">Ki</string> + <string name="invalid_contact_link">Érvénytelen hivatkozás!</string> + <string name="network_use_onion_hosts_required_desc_in_alert">A csatlakozáshoz Onion host-okra lesz szükség.</string> + <string name="new_in_version">Változások a %s verzióban</string> + <string name="network_use_onion_hosts_prefer_desc_in_alert">Onion host-okat használ, ha azok rendelkezésre állnak.</string> + <string name="smp_servers_invalid_address">Érvénytelen szervercím!</string> + <string name="thousand_abbreviation">k</string> + <string name="chat_item_ttl_none">soha</string> + <string name="new_desktop"><![CDATA[<i>(új)</i>]]></string> + <string name="ensure_smp_server_address_are_correct_format_and_unique">Győződj meg róla, hogy az SMP-kiszolgáló címei megfelelő formátumúak, sorszeparáltak és nincsenek duplikálva.</string> + <string name="network_use_onion_hosts_no_desc">Onion host-ok nem lesznek használva.</string> + <string name="custom_time_unit_minutes">perc</string> + <string name="learn_more">Tudj meg többet</string> + <string name="notification_new_contact_request">Új kapcsolattartási kérelem</string> + <string name="joining_group">Csatlakozás a csoporthoz</string> + <string name="linked_desktop_options">Összekapcsolt asztali eszköz beállítások</string> + <string name="rcv_group_event_invited_via_your_group_link">meghívva a csoport hivatkozásodon keresztül</string> + <string name="rcv_group_event_member_left">elhagyta</string> + <string name="linked_desktops">Összekapcsolt asztali eszközök</string> + <string name="la_no_app_password">Nincs alkalmazás jelkód</string> + <string name="muted_when_inactive">Némítás, ha inaktív!</string> + <string name="alert_title_group_invitation_expired">A meghívó lejárt!</string> + <string name="only_stored_on_members_devices">(csak a csoporttagok tárolják)</string> + <string name="moderate_verb">Moderál</string> + <string name="chat_preferences_on">be</string> + <string name="v5_1_japanese_portuguese_interface">Japán és Portugál kezelőfelület</string> + <string name="message_deletion_prohibited_in_chat">Ebben a csoportban tilos az üzenetek visszafordíthatatlan törlése.</string> + <string name="network_use_onion_hosts_no_desc_in_alert">Onion host-ok nem lesznek használva.</string> + <string name="remote_host_was_disconnected_toast"><![CDATA[A(z) <b>%s</b> eszközzel megszakadt a kapcsolat]]></string> + <string name="custom_time_unit_months">hónap</string> + <string name="privacy_message_draft">Üzenet vázlat</string> + <string name="v5_2_disappear_one_message">Egy üzenet eltüntetése</string> + <string name="v4_3_irreversible_message_deletion">Visszafordíthatatlan üzenettörlés</string> + <string name="videos_limit_desc">Egyszerre csak 10 videó küldhető el</string> + <string name="only_you_can_add_message_reactions">Csak te adhatsz hozzá üzenetreakciókat.</string> + <string name="group_member_status_left">elhagyta</string> + <string name="message_deletion_prohibited">Ebben a csevegésben tilos az üzenetek visszafordíthatatlan törlése.</string> + <string name="v4_3_voice_messages_desc">Max 40 másodperc, azonnal fogadható.</string> + <string name="description_via_contact_address_link_incognito">inkognitó a kapcsolattartási címen keresztül</string> + <string name="network_use_onion_hosts_required_desc">A csatlakozáshoz Onion host-okra lesz szükség. +\nKérjük, vedd figyelembe: .onion cím nélkül nem fogsz tudni csatlakozni a szerverekhez.</string> + <string name="v4_5_italian_interface">Olasz kezelőfelület</string> + <string name="system_restricted_background_in_call_title">Nincsenek háttérhívások</string> + <string name="messages_section_title">Üzenetek</string> + <string name="linked_mobiles">Összekapcsolt mobil eszközök</string> + <string name="incognito_info_allows">Lehetővé teszi, hogy egyetlen csevegőprofilon belül több anonim kapcsolat legyen, anélkül, hogy megosztott adatok lennének közöttük.</string> + <string name="delete_message_mark_deleted_warning">Az üzenet törlésre lesz jelölve. A címzett(ek) képes(ek) lesz(nek) felfedni ezt az üzenetet.</string> + <string name="leave_group_button">Elhagy</string> + <string name="ok">Rendben</string> + <string name="no_filtered_chats">Nincsenek szűrt csevegések</string> + <string name="invalid_data">Érvénytelen adat</string> + <string name="ensure_ICE_server_address_are_correct_format_and_unique">Győződj meg róla, hogy a WebRTC ICE-kiszolgáló címei megfelelő formátumúak, sorszeparáltak és nem duplikáltak.</string> + <string name="only_owners_can_enable_files_and_media">Csak a csoporttulajdonosok engedélyezhetik a fájlok- és a médiatartalmak küldését.</string> + <string name="loading_remote_file_title">A fájl betöltése</string> + <string name="no_contacts_to_add">Nincs hozzáadandó ismerős</string> + <string name="v4_5_message_draft">Üzenet vázlat</string> + <string name="display_name_invited_to_connect">meghívott, hogy csatlakozz</string> + <string name="add_contact">Egyszer használatos meghívó link</string> + <string name="notifications">Értesítések</string> + <string name="images_limit_desc">Egyszerre csak 10 kép küldhető el</string> + <string name="feature_offered_item_with_param">ajánlott %s: %2s</string> + <string name="not_compatible">Nem kompatibilis!</string> + <string name="make_profile_private">Tedd priváttá a profilodat!</string> + <string name="message_delivery_error_title">Üzenet kézbesítési hiba</string> + <string name="v4_5_multiple_chat_profiles">Több csevegőprofil</string> + <string name="marked_deleted_description">töröltnek jelölve</string> + <string name="user_mute">Elnémít</string> + <string name="link_a_mobile">Egy mobil összekapcsolása</string> + <string name="settings_notifications_mode_title">Értesítési szolgáltatás</string> + <string name="only_group_owners_can_enable_voice">Csak a csoporttulajdonosok engedélyezhetik a hangüzenetek küldését.</string> + <string name="only_client_devices_store_contacts_groups_e2e_encrypted_messages"><![CDATA[Csak a te eszközeid tárolják a felhasználói profilodat, névjegyeidet, csoportjaidat és a <b>2 rétegű végponttól-végpontig titkosítással</b> küldött üzeneteidet.]]></string> + <string name="invalid_migration_confirmation">Érvénytelen migrációs visszaigazolás</string> + <string name="only_group_owners_can_change_prefs">Csak a csoporttulajdonosok módosíthatják a csoportbeállításokat.</string> + <string name="no_history">Nincsenek előzmények</string> + <string name="invalid_QR_code">Érvénytelen QR-kód</string> + <string name="mark_read">Megjelölés olvasottként</string> + <string name="live">ÉLŐ</string> + <string name="mark_unread">Olvasatlannak jelölve</string> + <string name="icon_descr_more_button">Több</string> + <string name="auth_log_in_using_credential">Jelentkezz be a hitelesítő adataiddal</string> + <string name="invalid_message_format">érvénytelen üzenet formátum</string> + <string name="join_group_button">Csatlakozás</string> + <string name="shutdown_alert_desc">Az értesítések az alkalmazás elindításáig nem fognak működni.</string> + <string name="chat_preferences_off">ki</string>` + <string name="this_device_version"><![CDATA[<i>(ez az eszköz) v%s)</i>]]></string> + <string name="feature_offered_item">ajánlott %s</string> + <string name="button_leave_group">Csoport elhagyása</string> + <string name="unblock_member_desc">A %s-től érkező üzenetek megjelennek!</string> + <string name="many_people_asked_how_can_it_deliver"><![CDATA[Sokan kérdezték: <i>Ha a SimpleX Chat-nek nincs felhasználói azonosítója, hogyan lehet mégis üzeneteket küldeni?</i>]]></string> + <string name="alert_text_skipped_messages_it_can_happen_when">Ez akkor fordulhat elő, ha: +\n1. Az üzenetek az ismerősödnél 2 nap után, vagy a kiszolgálón 30 nap után lejártak. +\n2. Az üzenet visszafejtése sikertelen volt, mert Te vagy az ismerősöd régi adatbázis biztonsági mentést használt. +\n3. A kapcsolat sérült.</string> + <string name="group_member_role_observer">megfigyelő</string> + <string name="description_via_group_link_incognito">inkognitó a csoportos hivatkozáson keresztül</string> + <string name="network_use_onion_hosts_prefer_desc">Onion host-okat használ, ha azok rendelkezésre állnak.</string> + <string name="invite_friends">Barátok meghívása</string> + <string name="color_surface">Menük és figyelmeztetések</string> + <string name="icon_descr_add_members">Tagok meghívása</string> + <string name="group_preview_join_as">Csatlakozás mint %s</string> + <string name="no_selected_chat">Nincs kiválasztott csevegés</string> + <string name="users_delete_data_only">Csak helyi profiladatok</string> + <string name="description_via_one_time_link_incognito">inkognitó Egyszer használatos link által</string> + <string name="share_text_moderated_at">Moderálva ekkor: %s</string> + <string name="one_time_link">Egyszer használatos meghívó link</string> + <string name="invalid_name">Érvénytelen név!</string> + <string name="email_invite_subject">Beszélgessünk a SimpleX Chat-ben</string> + <string name="info_row_moderated_at">Moderálva ekkor</string> + <string name="v4_4_live_messages">Élő üzenetek</string> + <string name="mark_code_verified">Ellenőrzöttként jelölve</string> + <string name="v5_2_message_delivery_receipts">Üzenet kézbesítési bizonylatok!</string> + <string name="image_descr_link_preview">hivatkozás előnézeti képe</string> + <string name="leave_group_question">Elhagyod a csoportot?</string> + <string name="chat_preferences_no">nem</string> + <string name="v4_5_reduced_battery_usage_descr">Hamarosan további fejlesztések érkeznek!</string> + <string name="feature_off">ki</string> + <string name="install_simplex_chat_for_terminal">Telepítsd a SimpleX Chat-et a terminálhoz</string> + <string name="self_destruct_new_display_name">Új megjelenített név:</string> + <string name="new_passphrase">Új jelmondat…</string> + <string name="callstatus_missed">nem fogadott hívás</string> + <string name="database_migrations">Migrációk: %s</string> + <string name="in_reply_to">Válasz neki</string> + <string name="notification_preview_mode_message">Üzenet szövege</string> + <string name="notifications_will_be_hidden">Az értesítések csak az alkalmazás bezárásáig érkeznek!</string> + <string name="info_menu">Információ</string> + <string name="settings_section_title_messages">ÜZENETEK ÉS FÁJLOK</string> + <string name="group_member_role_member">tag</string> + <string name="make_private_connection">Privát kapcsolat létrehozása</string> + <string name="moderated_item_description">Moderálva %s által</string> + <string name="import_theme_error_desc">Győződj meg róla, hogy a fájl helyes YAML-szintaxist tartalmaz. Exportáld a témát, hogy legyen egy példa a téma-fájl szerkezetére.</string> + <string name="italic_text">dőlt</string> + <string name="non_content_uri_alert_title">Érvénytelen fájl elérési útvonal</string> + <string name="connect_via_group_link">Csatlakozol a csoporthoz?</string> + <string name="status_no_e2e_encryption">nincs e2e titkosítás</string> + <string name="new_database_archive">Új adatbázis-archívum</string> + <string name="live_message">Élő üzenet!</string> + <string name="invite_to_group_button">Meghívás a csoportba</string> + <string name="lock_after">Lezárás miután</string> + <string name="incoming_audio_call">Bejövő hanghívás</string> + <string name="keychain_error">Kulcstartó hiba</string> + <string name="join_group_question">Csatlakozol a csoporthoz?</string> + <string name="incognito_info_protects">Az inkognitó mód úgy védi a magánszférádat, hogy minden egyes kapcsolathoz új, véletlenszerű profilt használ.</string> + <string name="v5_2_more_things_descr">- stabilabb üzenetkézbesítés. +\n- egy kicsit jobb csoportok. +\n- és még sok más!</string> + <string name="v5_1_message_reactions">Üzenet reakciók</string> + <string name="no_connected_mobile">Nincs csatlakoztatott mobil eszköz</string> + <string name="network_status">Hálózat állapota</string> + <string name="new_passcode">Új Jelkód</string> + <string name="message_delivery_error_desc">Valószínűleg ez az ismerősöd törölte a kapcsolatát veled.</string> + <string name="join_group_incognito_button">Csatlakozás inkognitóban</string> + <string name="open_chat">Chat megnyitása</string> + <string name="callstatus_rejected">elutasított hívás</string> + <string name="onboarding_notifications_mode_periodic">Rendszeres</string> + <string name="feature_received_prohibited">fogadott, tiltott</string> + <string name="connect_plan_repeat_connection_request">Kapcsolódási kérés megismétlése?</string> + <string name="only_you_can_delete_messages">Kizárólag csak te tudsz véglegesen törölni üzeneteket (az ismerősöd csak megjelölheti azokat törlendőként). (24 óra)</string> + <string name="role_in_group">Szerepkör</string> + <string name="simplex_link_contact">SimpleX ismerős azonosítója</string> + <string name="stop_file__confirm">Megállítás</string> + <string name="smp_servers_preset_server">Előre beállított szerver</string> + <string name="add_contact_or_create_group">Új chat kezdése</string> + <string name="opensource_protocol_and_code_anybody_can_run_servers">Nyílt forráskódú protokoll és program - bárki üzemeltethet szervereket.</string> + <string name="rcv_group_event_open_chat">Megnyitás</string> + <string name="network_option_protocol_timeout">Protokoll időtúllépés</string> + <string name="secret_text">titok</string> + <string name="settings_notification_preview_mode_title">Előnézet mutatása</string> + <string name="callstate_waiting_for_confirmation">várakozás a visszaigazolásra…</string> + <string name="stop_file__action">Fájl megállítása</string> + <string name="description_via_group_link">csoport linken keresztül</string> + <string name="network_option_ping_interval">PING időköze</string> + <string name="send_disappearing_message">Eltűnő üzenet küldése</string> + <string name="self_destruct_passcode">Önmegsemmisítési jelkód</string> + <string name="save_and_update_group_profile">Mentés és a csoport profil frissítése</string> + <string name="your_privacy">A te adatvédelmed</string> + <string name="your_simplex_contact_address">A te SimpleX azonosítód</string> + <string name="alert_text_fragment_please_report_to_developers">Kérlek jelentsd a fejlesztőknek!</string> + <string name="people_can_connect_only_via_links_you_share">Az emberek kizárólag az általad megosztott link alapján kapcsolódhatnak hozzád.</string> + <string name="prohibit_sending_disappearing">Az eltűnő üzenetek küldése le van tiltva.</string> + <string name="only_you_can_send_voice">Kizárólag te tudsz hangüzeneteket küldeni.</string> + <string name="update_network_settings_confirmation">Frissítés</string> + <string name="icon_descr_video_snd_complete">Videó elküldve</string> + <string name="update_database_passphrase">Adatbázis jelmondat megváltoztatása</string> + <string name="turn_off_system_restriction_button">App beállítások megnyitása</string> + <string name="passcode_not_changed">A jelkód nem változott!</string> + <string name="refresh_qr_code">Frissítés</string> + <string name="custom_time_picker_select">Választás</string> + <string name="only_you_can_make_calls">Kizárólag te tudsz hívásokat indítani.</string> + <string name="smp_server_test_secure_queue">Biztonságos várólista</string> + <string name="rate_the_app">Értékeld az appot</string> + <string name="share_invitation_link">Egyszer használatos link megosztása</string> + <string name="database_restore_error">Hiba az adatbázis visszaállításakor</string> + <string name="group_members_2">%s és %s</string> + <string name="chat_preferences_you_allow">Te engedélyezed</string> + <string name="v4_5_reduced_battery_usage">Takarékos akkumulátor használat</string> + <string name="save_and_notify_contacts">Mentés és az ismerősök értesítése</string> + <string name="group_welcome_preview">Előnézet</string> + <string name="use_chat">Használd a chatet</string> + <string name="share_verb">Megosztás</string> + <string name="received_message">Fogadott üzenet</string> + <string name="button_welcome_message">Üdvözlő üzenet</string> + <string name="rcv_group_event_n_members_connected">%s, %s és %d további tag csatlakozott</string> + <string name="only_your_contact_can_make_calls">Kizárólag az ismerősöd tud hívást indítani.</string> + <string name="settings_section_title_themes">SZÍNSÉMÁK</string> + <string name="videos_limit_title">Túl sok videó!</string> + <string name="stop_chat_to_enable_database_actions">Chat szolgáltatás megállítása az adatbázis műveletek elvégzéséhez.</string> + <string name="welcome">Üdvözöllek!</string> + <string name="v5_1_self_destruct_passcode">Önmegsemmisítési jelkód</string> + <string name="connect_via_link_or_qr_from_clipboard_or_in_person">(beolvasás vagy vágólapról beillesztés)</string> + <string name="waiting_for_video">Videóra várakozás</string> + <string name="reply_verb">Válasz</string> + <string name="connect_plan_this_is_your_own_one_time_link">Ez a te egyszer használatos linked!</string> + <string name="ntf_channel_calls">SimpleX Chat hívások</string> + <string name="connect_use_new_incognito_profile">Az új inkognító profil használata</string> + <string name="contact_developers">Kérlek frissítsd az appot és jelentsd a fejlesztőknek!</string> + <string name="theme_simplex">SimpleX</string> + <string name="send_link_previews">Link előnézetek küldése</string> + <string name="rcv_conn_event_verification_code_reset">biztonsági kód megváltozott</string> + <string name="notification_preview_mode_contact_desc">Kizárólag az ismerős mutatása</string> + <string name="icon_descr_speaker_on">Hangszóró bekapcsolva</string> + <string name="restart_the_app_to_use_imported_chat_database">Indítsd újra az appot, hogy importált chat adatbázist használj.</string> + <string name="icon_descr_sent_msg_status_unauthorized_send">jogosulatlan küldés</string> + <string name="only_your_contact_can_send_voice">Kizárólag az ismerősöd tud hangüzeneteket küldeni.</string> + <string name="icon_descr_settings">Beállítások</string> + <string name="scan_qr_to_connect_to_contact">Kapcsolat létrehozásához az ismerősöd beolvassa a QR-kódodat vagy a linket használja az appban.</string> + <string name="callstate_received_confirmation">visszaigazolás fogadása…</string> + <string name="scan_code_from_contacts_app">A biztonsági kód beolvasása az ismerősöd appjából.</string> + <string name="observer_cant_send_message_desc">Kérlek vedd fel a kapcsolatot a csoport adminnal!</string> + <string name="icon_descr_video_on">Videó bekapcsolva</string> + <string name="display_name__field">Profil neve:</string> + <string name="paste_button">Beillesztés</string> + <string name="thank_you_for_installing_simplex">Köszönjük, hogy telepítetted a SimpleX Chatet!</string> + <string name="star_on_github">Csillag a GitHub-on</string> + <string name="remove_member_confirmation">Eltávolítás</string> + <string name="search_verb">Keresés</string> + <string name="sync_connection_force_question">Titkosítás újraegyeztetése?</string> + <string name="self_destruct_passcode_enabled">Az önmegsemmisítési jelkód engedélyezve!</string> + <string name="v4_2_security_assessment">Biztonsági kiértékelés</string> + <string name="color_title">Cím</string> + <string name="icon_descr_send_message">Üzenet Elküldése</string> + <string name="restore_database">Adatbázis mentés visszaállítása</string> + <string name="revoke_file__confirm">Visszavon</string> + <string name="ask_your_contact_to_enable_voice">Kérd meg az ismerősödet, hogy engedélyezze a hangüzenetek küldését!</string> + <string name="description_you_shared_one_time_link">egyszer használatos linket osztottál meg</string> + <string name="simplex_link_mode_browser_warning">A link megnyitása böngészőben gyengítheti az adatvédelem és biztonság szintjét. A megbízhatatlan SimpleX linkek vörössel vannak kiemelve.</string> + <string name="your_ice_servers">Az ICE szervereid</string> + <string name="you_accepted_connection">A kapcsolódást elfogadtad</string> + <string name="reject_contact_button">Elutasítás</string> + <string name="notification_preview_mode_message_desc">Ismerős és üzenet mutatása</string> + <string name="settings_section_title_settings">BEÁLLÍTÁSOK</string> + <string name="save_profile_password">Felhasználói fiók jelszavának elmentése</string> + <string name="stop_snd_file__title">Fájl küldés megszakítása?</string> + <string name="unlink_desktop_question">Számítőgép leválasztása?</string> + <string name="voice_messages_prohibited">A hangüzenetek le vannak tilva!</string> + <string name="compose_send_direct_message_to_connect">A kapcsolódáshoz közvetlen üzenet küldése</string> + <string name="network_option_ping_count">PING számláló</string> + <string name="show_developer_options">Fejlesztői beállítások mutatása</string> + <string name="rcv_group_event_1_member_connected">%s csatlakozva</string> + <string name="theme_system">Rendszer</string> + <string name="network_use_onion_hosts_prefer">Amikor elérhető</string> + <string name="voice_message_with_duration">Hangüzenet (%1$s)</string> + <string name="current_version_timestamp">%s (jelenlegi)</string> + <string name="smp_servers_your_server">A te szervered</string> + <string name="random_port">Véletlen</string> + <string name="share_with_contacts">Megosztás ismerősökkel...</string> + <string name="sender_you_pronoun">te</string> + <string name="you_have_no_chats">Nincsenek chat üzeneteid</string> + <string name="send_disappearing_message_send">Küldés</string> + <string name="chat_item_ttl_seconds">%s másodperc</string> + <string name="recipient_colon_delivery_status">%s: %s</string> + <string name="system_restricted_background_desc">A SimpleX nem tud a háttérben futni. Csak az alkalmazás futása közben fogod az üzeneteket megkapni.</string> + <string name="images_limit_title">Túl sok kép!</string> + <string name="save_archive">Archív mentése</string> + <string name="group_members_n">%s, %s és %d tag</string> + <string name="auth_stop_chat">Chat szolgáltatás megállítása</string> + <string name="simplex_link_mode">SimpleX linkek</string> + <string name="v4_4_disappearing_messages_desc">Az elküldött üzenetek törlésre kerülnek a beállított idő után.</string> + <string name="user_unmute">Némítás feloldása</string> + <string name="share_text_sent_at">Elküldve ekkor: %s</string> + <string name="connect_use_current_profile">Jelenlegi profil használata</string> + <string name="this_device">Ez az eszköz</string> + <string name="share_address_with_contacts_question">Megosztod a címet az ismerőseiddel?</string> + <string name="profile_password">Profil jelszó</string> + <string name="theme">Színséma</string> + <string name="remove_passphrase_from_settings">Jelmondat eltávolítása a beállításokból?</string> + <string name="simplex_link_group">SimpleX csoport link</string> + <string name="icon_descr_waiting_for_image">Képre várakozás</string> + <string name="self_destruct">Önmegsemmisítés</string> + <string name="callstate_waiting_for_answer">várakozás válaszra…</string> + <string name="text_field_set_contact_placeholder">Ismerős nevének beállítása…</string> + <string name="unblock_member_button">Tag feloldása</string> + <string name="scan_QR_code">QR-kód beolvasása</string> + <string name="smp_servers_test_server">Szerver tesztelése</string> + <string name="send_us_an_email">Írj nekünk e-mailben!</string> + <string name="conn_stats_section_title_servers">SZERVEREK</string> + <string name="smp_servers_test_servers">Szerverek tesztelése</string> + <string name="la_lock_mode_passcode">Jelkód bevitele</string> + <string name="la_mode_system">Rendszer</string> + <string name="submit_passcode">Elküld</string> + <string name="security_code">Biztonsági kód</string> + <string name="enter_correct_current_passphrase">Kérlek írd be a helyes jelmondatot!</string> + <string name="prohibit_message_deletion">Az üzenetek véglegesen való törlése le van tiltva.</string> + <string name="prohibit_message_reactions">Az üzenetekre adott emoji reakciók le vannak tiltva.</string> + <string name="use_random_passphrase">Véletlenszerű jelmondat használata</string> + <string name="call_connection_peer_to_peer">ponttól-pontig</string> + <string name="run_chat_section">CHAT SZOLGÁLTATÁS INDÍTÁSA</string> + <string name="paste_the_link_you_received">Fogadott link beillesztése</string> + <string name="smp_save_servers_question">Szerverek elmentése?</string> + <string name="v4_2_security_assessment_desc">A SimpleX Chat biztonsága a Trail of Bits által lett auditálva.</string> + <string name="rcv_group_event_updated_group_profile">módosított csoport profil</string> + <string name="settings_section_title_support">TÁMOGASD A SIMPLEX CHATET!</string> + <string name="simplex_service_notification_title">SimpleX Chat szolgáltatás</string> + <string name="observer_cant_send_message_title">Nem tudsz üzeneteket küldeni!</string> + <string name="is_verified">%s ellenőrzött</string> + <string name="password_to_show">Jelszó mutatása</string> + <string name="privacy_and_security">Adatvédelem és biztonság</string> + <string name="button_remove_member">Tag eltávolítása</string> + <string name="passcode_set">A jelkód beállítva!</string> + <string name="sent_message">Elküldött üzenet</string> + <string name="select_contacts">Ismerősök kiválasztása</string> + <string name="unknown_message_format">ismeretlen üzenet formátum</string> + <string name="smp_servers_save">Szerverek elmentése</string> + <string name="group_welcome_title">Üdvözlő üzenet</string> + <string name="network_option_seconds_label">mp</string> + <string name="profile_update_will_be_sent_to_contacts">Profil változtatása frissítésre kerül az ismerőseidnél.</string> + <string name="v5_3_simpler_incognito_mode">Egyszerűsített inkognító mód</string> + <string name="save_welcome_message_question">Üdvözlőszöbeg elmentése?</string> + <string name="restart_the_app_to_create_a_new_chat_profile">Indítsd újra az appot, hogy új felhasználói fiókot hozz létre.</string> + <string name="toast_permission_denied">Engedély megtagadva!</string> + <string name="icon_descr_call_pending_sent">Főggőben lévő hívás</string> + <string name="opening_database">Adatbázis megnyitása…</string> + <string name="shutdown_alert_question">Leállítás?</string> + <string name="enter_passphrase_notification_title">Jelmondat szükséges</string> + <string name="onboarding_notifications_mode_title">Privát értesítések</string> + <string name="you_invited_a_contact">Meghívtál egy ismerőst</string> + <string name="is_not_verified">%s nincs ellenőrizve</string> + <string name="contact_tap_to_connect">A csatlakozáshoz érintsd meg</string> + <string name="this_device_name">Ennek az eszköznek a neve</string> + <string name="your_current_profile">A te jelenlegi profilod</string> + <string name="smp_server_test_upload_file">Fájl feltöltése</string> + <string name="prohibit_calls">Hang- és videóhívások tiltása.</string> + <string name="network_use_onion_hosts_required">Megkövetelt</string> + <string name="ntf_channel_messages">SimpleX chat üzenetek</string> + <string name="restore_database_alert_confirm">Visszaállítás</string> + <string name="setup_database_passphrase">Adatbázis jelmondat beállítása</string> + <string name="color_sent_message">Elküldött üzenet</string> + <string name="notifications_mode_periodic">Rendszeresen elindul</string> + <string name="connect_plan_this_is_your_own_simplex_address">Ez a te saját SimpleX azonosítód!</string> + <string name="group_member_status_removed">eltávolítva</string> + <string name="share_link">Link megosztása</string> + <string name="icon_descr_simplex_team">SimpleX Csapat</string> + <string name="image_descr_profile_image">profilkép</string> + <string name="your_chat_profiles">A te chat profiljaid</string> + <string name="group_member_role_owner">tulajdonos</string> + <string name="la_notice_turn_on">Bekapcsolás</string> + <string name="rcv_group_event_3_members_connected">%s, %s és %s csatlakozott</string> + <string name="simplex_link_invitation">SimpleX egyszer használatos meghívó</string> + <string name="your_calls">A te hívásaid</string> + <string name="icon_descr_sent_msg_status_send_failed">küldés sikertelen</string> + <string name="theme_colors_section_title">SZÍNSÉMA SZÍNEK</string> + <string name="network_options_revert">Visszaállít</string> + <string name="restore_database_alert_desc">Kérlek írd be az előző jelszót az adatbázis visszaállítása után. Ez a művelet visszafordíthatatlan.</string> + <string name="color_secondary">Másodlagos</string> + <string name="settings_section_title_socks">SOCKS PROXY</string> + <string name="save_servers_button">Mentés</string> + <string name="settings_restart_app">Újraindítás</string> + <string name="smp_servers">Üzenetküldő (SMP) szerverek</string> + <string name="video_descr">Videó</string> + <string name="save_auto_accept_settings">Automatikus elfogadási beállítások mentése</string> + <string name="sync_connection_force_confirm">Újraegyzetetés</string> + <string name="icon_descr_waiting_for_video">Videóra várakozás</string> + <string name="your_XFTP_servers">A te Simplex fájl küldő (XFTP) szervereid</string> + <string name="icon_descr_video_off">Videó kikapcsolva</string> + <string name="v4_5_private_filenames">Privát fájl nevek</string> + <string name="save_settings_question">Beállítások elmentése?</string> + <string name="la_mode_passcode">Jelkód</string> + <string name="unknown_error">Ismeretlen hiba</string> + <string name="smp_servers_your_server_address">A te szerver címed</string> + <string name="auth_open_chat_console">Chat konzol megnyitása</string> + <string name="remove_member_button">Tag eltávolítása</string> + <string name="set_database_passphrase">Beállított adatbázis jelmondat</string> + <string name="view_security_code">Biztonsági kód megtekintése</string> + <string name="unblock_member_question">Tag feloldása?</string> + <string name="sender_may_have_deleted_the_connection_request">A küldő törölhette a kapcsolódási kérelmet.</string> + <string name="wrong_passphrase">Téves adatbázis jelmondat</string> + <string name="your_SMP_servers">A te Simplex chat (SMP) szervereid</string> + <string name="send_receipts_disabled_alert_title">Üzenet kézbesítési jelentés letiltva</string> + <string name="open_database_folder">Adatbázis mappa megnyitása</string> + <string name="description_via_one_time_link">egyszer használatos linken keresztül</string> + <string name="set_group_preferences">Csoportbeállítások megadása</string> + <string name="simplex_link_connection">%1$s keresztül</string> + <string name="chat_preferences_yes">igen</string> + <string name="voice_message">Hangüzenet</string> + <string name="settings_section_title_use_from_desktop">Használat asztali kliensről</string> + <string name="settings_section_title_you">TE</string> + <string name="network_proxy_port">port %d</string> + <string name="to_connect_via_link_title">Kapcsolódás link által</string> + <string name="share_address">Azonosító megosztása</string> + <string name="smp_servers_scan_qr">Szerver QR-kód beolvasása</string> + <string name="stop_chat_confirmation">Megállítás</string> + <string name="stop_sharing_address">Azonosítód megosztásának szüneteltetése?</string> + <string name="auth_open_chat_profiles">Chat profilok megnyitása</string> + <string name="connect_plan_repeat_join_request">Csatlakozási kérés megismétlése?</string> + <string name="waiting_for_image">Képre várakozás</string> + <string name="v4_3_voice_messages">Hangüzenetek</string> + <string name="button_remove_member_question">Tag eltávolítása?</string> + <string name="verify_security_code">Biztonsági kód megtekintése</string> + <string name="rcv_group_event_user_deleted">eltávolított téged</string> + <string name="simplex_address">SimpleX cím</string> + <string name="show_dev_options">Mutat:</string> + <string name="callstate_received_answer">fogadott válasz…</string> + <string name="restore_database_alert_title">Adatbázis mentés visszaállítása?</string> + <string name="simplex_service_notification_text">Üzenetek fogadása…</string> + <string name="rcv_group_event_2_members_connected">%s és %s csatlakozva</string> + <string name="you_are_observer">megfigyelő vagy</string> + <string name="port_verb">Port</string> + <string name="set_passcode">Jelkód beállítása</string> + <string name="whats_new">Milyen újdonságok vannak</string> + <string name="connect_plan_open_group">Csoport megnyitása</string> + <string name="info_row_sent_at">Elküldve ekkor</string> + <string name="prohibit_sending_voice">A hangüzenetek küldése le van tiltva.</string> + <string name="privacy_show_last_messages">Utolsó üzenetek megjelenítése</string> + <string name="smp_servers_preset_address">Előre beállított szerver címe</string> + <string name="periodic_notifications_disabled">Rendszeres értesítések letiltva!</string> + <string name="passcode_changed">A jelkód megváltozott!</string> + <string name="notifications_mode_off">Akkor fut, amikor az alkalmazás meg van nyitva</string> + <string name="this_QR_code_is_not_a_link">Ez a QR-kód nem egy link!</string> + <string name="waiting_for_file">Fájlra várakozás</string> + <string name="core_simplexmq_version">simplexmq: v%s (%2s)</string> + <string name="unlink_desktop">Szétkapcsolás</string> + <string name="incognito_random_profile">A te véletlenszerű profilod</string> + <string name="wrong_passphrase_title">Téves jelmondat!</string> + <string name="prohibit_message_reactions_group">Az üzenetekre adott emoji reakciók le vannak tiltva.</string> + <string name="language_system">Rendszer</string> + <string name="icon_descr_received_msg_status_unread">olvasatlan</string> + <string name="icon_descr_server_status_pending">Függő</string> + <string name="personal_welcome">Üdvözöllek %1$s!</string> + <string name="remove_passphrase_from_keychain">Jelmondat eltávolítása a Keystrore-ból?</string> + <string name="auth_unlock">Feloldás</string> + <string name="prohibit_sending_disappearing_messages">Az eltűnő üzenetek küldése le van tiltva.</string> + <string name="gallery_video_button">Videó</string> + <string name="update_database">Frissítés</string> + <string name="open_verb">Megnyitás</string> + <string name="periodic_notifications">Rendszeres értesítések</string> + <string name="alert_title_skipped_messages">Kihagyott üzenetek</string> + <string name="prohibit_sending_voice_messages">A hangüzenetek küldése le van tiltva.</string> + <string name="set_contact_name">Ismerős nevének beállítása...</string> + <string name="only_you_can_send_disappearing">Kizárólag te tudsz eltűnő üzeneteket küldeni.</string> + <string name="share_image">Kép/videó megoszása…</string> + <string name="group_info_member_you">te: %1$s</string> + <string name="your_preferences">A te beállításaid</string> + <string name="reset_color">Színek alaphelyzetbe állítása</string> + <string name="network_options_save">Mentés</string> + <string name="switch_verb">Váltás</string> + <string name="paste_the_link_you_received_to_connect_with_your_contact">Illeszd be a kapott linket az ismerősödhöz való kapcsolódáshoz…</string> + <string name="scan_code">Kód beolvasása</string> + <string name="open_port_in_firewall_title">Port megnyitása a tűzfalon</string> + <string name="callstate_starting">indítás…</string> + <string name="save_color">Szín elmentése</string> + <string name="settings_shutdown">Leállítás</string> + <string name="icon_descr_sent_msg_status_sent">elküldve</string> + <string name="network_socks_toggle_use_socks_proxy">SOCKS proxy használata</string> + <string name="send_live_message">Élő üzenet küldése</string> + <string name="privacy_redefined">Adatvédelem újraértelmezve</string> + <string name="voice_message_send_text">Hangüzenet…</string> + <string name="protect_app_screen">App képernyőjének védelme</string> + <string name="show_QR_code">QR-kód mutatása</string> + <string name="icon_descr_video_call">videóhívás</string> + <string name="unfavorite_chat">Nem kedvenc</string> + <string name="send_receipts">Üzenet kézbesítési jelentések</string> + <string name="icon_descr_address">SimpleX cím</string> + <string name="chat_help_tap_button">Érintsd meg a gombot</string> + <string name="save_and_notify_contact">Mentés és az ismerős értesítése</string> + <string name="icon_descr_call_rejected">Elutasított hívás</string> + <string name="network_socks_proxy_settings">SOCKS proxy beállítások</string> + <string name="image_descr_qr_code">QR-kód</string> + <string name="renegotiate_encryption">Titkosítás újraegyeztetése</string> + <string name="remove_passphrase">Eltávolítás</string> + <string name="network_use_onion_hosts">TOR .onion hostok használata</string> + <string name="reveal_verb">Bemutatás</string> + <string name="la_lock_mode">SimpleX Zár mód</string> + <string name="revoke_file__action">Fájl visszavonása</string> + <string name="xftp_servers">Fájl küldő/fogadó (XFTP) SimpleX szerverek</string> + <string name="prohibit_sending_files">A fájlok- és a médiatartalom küldése le van tiltva.</string> + <string name="share_file">Fájl megosztása…</string> + <string name="save_verb">Mentés</string> + <string name="call_connection_via_relay">közvetítő szerveren keresztül</string> + <string name="stop_sharing">Megosztás leállítása</string> + <string name="snd_group_event_member_deleted">eltávolítottad %1$s</string> + <string name="save_passphrase_and_open_chat">Jelmondat elmentése és chat megnyitása</string> + <string name="save_preferences_question">Beállítások elmentése?</string> + <string name="first_platform_without_user_ids">Az első chat rendszer bármiféle felhasználó azonosító nélkül - privátra lett tervezre.</string> + <string name="prohibit_direct_messages">A tagoknak való közvetlen üzenetküldés le van tiltva.</string> + <string name="network_enable_socks">SOCKS proxy használata?</string> + <string name="icon_descr_speaker_off">Hangszóró kikapcsolva</string> + <string name="custom_time_unit_weeks">hét</string> + <string name="show_call_on_lock_screen">Mutasd</string> + <string name="webrtc_ice_servers">WebRTC ICE szerverek</string> + <string name="revoke_file__title">Fájl visszavonása?</string> + <string name="button_send_direct_message">Közvetlen üzenet küldése</string> + <string name="reject">Elutasítás</string> + <string name="send_verb">Küldés</string> + <string name="la_lock_mode_system">Rendszer hitelesítés</string> + <string name="simplex_link_mode_browser">Böngészőn keresztül</string> + <string name="v4_6_hidden_chat_profiles_descr">A chat profiljaid védelme jelszóval!</string> + <string name="only_your_contact_can_send_disappearing">Kizárólag az ismerősöd tud eltűnő üzeneteket küldeni.</string> + <string name="your_ICE_servers">A te ICE szervereid</string> + <string name="scan_qr_code_from_desktop">QR-kód beolvasása asztali számítógépről</string> + <string name="image_descr_simplex_logo">SimpleX Logo</string> + <string name="unblock_member_confirmation">Feloldás</string> + <string name="unmute_chat">Némítás feloldása</string> + <string name="open_simplex_chat_to_accept_call">SimpleX chat megnyitása a hívás fogadásához</string> + <string name="stop_rcv_file__title">Fájl fogadás megszakítása?</string> + <string name="v5_4_more_things_descr">- opcionális értesítés a törölt ismerősök számára +\n- profil nevek szóközökkel +\n- és továbbiak!</string> + <string name="v5_0_polish_interface">Lengyel kezelőfelület</string> + <string name="smp_servers_use_server">Használd a szervert</string> + <string name="share_text_received_at">Fogadva ekkor: %s</string> + <string name="la_notice_title_simplex_lock">SimpleX Zár</string> + <string name="save_and_notify_group_members">Mentés és a csoporttagok értesítése</string> + <string name="reset_verb">Alaphelyzetbe álítás</string> + <string name="only_your_contact_can_add_message_reactions">Kizárólag az ismerősöd tud emoji reakciókat adni az üzenetekre.</string> + <string name="voice_messages">Hangüzenetek</string> + <string name="snd_group_event_user_left">te távoztál</string> + <string name="icon_descr_record_voice_message">Hangüzenet rögzítése</string> + <string name="auth_simplex_lock_turned_on">SimpleX Zár bekapcsolva</string> + <string name="member_contact_send_direct_message">közvetlen üzenet küldése</string> + <string name="scan_from_mobile">Telefonről beolvasás</string> + <string name="verify_connections">Kapcsolatok ellenőrzése</string> + <string name="share_message">Üzenet megosztása…</string> + <string name="custom_time_unit_seconds">másodperc</string> + <string name="lock_not_enabled">SimpleX Zár nincs engedélyezve!</string> + <string name="chat_lock">SimpleX Zár</string> + <string name="your_settings">A te beállításaid</string> + <string name="your_chat_database">Chat adatbázis használata</string> + <string name="rcv_group_event_member_deleted">%1$s eltávolítva</string> + <string name="smp_servers_test_failed">Szerver teszt sikertelen!</string> + <string name="verify_connection">Kapcsolat ellenőrzése</string> + <string name="whats_new_read_more">Tudj meg többet</string> + <string name="sender_cancelled_file_transfer">A küldő megszakította a fájl átvitelt.</string> + <string name="stop_chat_question">Chat szolgáltatás megállítása?</string> + <string name="info_row_received_at">Fogadva ekkor</string> + <string name="accept_feature_set_1_day">Beállítva 1 nap</string> + <string name="user_unhide">Felfedés</string> + <string name="color_received_message">Fogadott üzenet</string> + <string name="only_your_contact_can_delete">Kizárólag az ismerősöd tud véglegesen törölni üzeneteket (te csak törlendőként tudod megjelölni azokat). (24 óra)</string> + <string name="self_destruct_passcode_changed">Az önmegsemmisítési jelkód megváltozott!</string> + <string name="using_simplex_chat_servers">SimpleX Chat szerverek használatban.</string> + <string name="use_simplex_chat_servers__question">SimpleX Chat szerverek használata?</string> + <string name="unhide_chat_profile">Chat profil felfedése</string> + <string name="v5_0_large_files_support">Videók és fájlok 1Gb méretig</string> + <string name="network_option_tcp_connection_timeout">TCP kapcsolat időtúllépés</string> + <string name="connect__your_profile_will_be_shared">A te %1$s SimpleX azonosítód megosztásra kerül.</string> + <string name="you_are_already_connected_to_vName_via_this_link">Már csatlakozva vagy hozzá: %1$s.</string> + <string name="your_current_chat_database_will_be_deleted_and_replaced_with_the_imported_one">A jelenlegi chat adatbázisod TÖRLÉSRE és FELCSERÉLÉSRE kerül az importált által! +\nEz a művelet nem visszavonható - a profilod, az ismerőseid, a chat üzeneteid és fájljaid mind véglegesen elvesznek!</string> + <string name="chat_with_the_founder">Ötletek és kérdések beküldése</string> + <string name="database_downgrade_warning">Figyelem: néhány adatot elveszíthetsz!</string> + <string name="tap_to_start_new_chat">Új chat kezdése</string> + <string name="waiting_for_desktop">Várakozás a számítógépre…</string> + <string name="next_generation_of_private_messaging">A privát chatelés új generációja</string> + <string name="update_network_settings_question">Hálózati beállítások megváltoztatása?</string> + <string name="waiting_for_mobile_to_connect">Várakozás a mobiltelefon csatlakozására:</string> + <string name="v4_4_verify_connection_security">Kapcsolat biztonságának ellenőrzése</string> + <string name="sending_files_not_yet_supported">fájlok küldése egyelőre még nem támogatott</string> + <string name="snd_conn_event_switch_queue_phase_completed_for_member">Megváltoztattad az azonosítót erre: %s</string> + <string name="receiving_files_not_yet_supported">fájlok fogadása egyelőre még nem támogatott</string> + <string name="save_group_profile">Csoport profil elmentése</string> + <string name="network_options_reset_to_defaults">Alaphelyzetbe állítás</string> + <string name="connection_error_auth_desc">Hacsak az ismerősöd nem törölte a kapcsolatot, vagy ez a hivatkozás már használatban volt, akkor ez hiba lehet – kérjük, jelentsd. +\nA csatlakozáshoz kérd meg az ismerősöd, hogy hozzon létre egy másik kapcsolati hivatkozást, és ellenőrizze, hogy a hálózati kapcsolat stabil-e.</string> + <string name="video_call_no_encryption">videóhívás (nem e2e titkosított)</string> + <string name="smp_servers_use_server_for_new_conn">Alkalmazás új kapcsolatokhoz</string> + <string name="periodic_notifications_desc">Az app rendszeresen lekéri az új üzeneteket - ez naponta néhány százalék akkumulátort használ. Az app nem használja a Google push értesítési rendszert — az eszközödön lévő adat nem kerül megküldésre a szervereknek.</string> + <string name="paste_desktop_address">Számítógép címének beillesztése</string> + <string name="description_via_contact_address_link">ismerős azonosítójának linkjén keresztül</string> + <string name="to_preserve_privacy_simplex_has_background_service_instead_of_push_notifications_it_uses_a_few_pc_battery"><![CDATA[Az adatvédelmed megőrzése érdekkében a Google push értesítési rendszer helyett az app a <b>SimpleX háttérszolgáltatást </b> használja - ez naponta néhány százalék akkumulátort használ.]]></string> + <string name="alert_text_connection_pending_they_need_to_be_online_can_delete_and_retry">Az ismerősöd online kell legyen ahhoz, hogy a kapcsolat létrejöjjön. +\nMegszakíthatod ezt a kapcsolatfelvételt és törölheted az ismerőst (és később ismét megpróbálhatod egy új linkkel)</string> + <string name="restore_passphrase_not_found_desc">Jelmondat nem található a Keystore-ban, kérlek írd be kézileg. Ez akkor történhet, ha helyreállítottad az appot a backup funkcióval. Ha nem így történt, az esetben lépj kapcsolatba a fejlesztőkkel!</string> + <string name="your_contacts_will_remain_connected">Az ismerőseid továbbra is megmaradnak</string> + <string name="error_xftp_test_server_auth">A szervernek engedélyre van szüksége a várólisták létrehozásához, ellenőrizd a jelszavadat</string> + <string name="database_initialization_error_desc">Az adatbázis nem működik megfelelően. Koppints a további információkért</string> + <string name="stop_snd_file__message">A fájl küldése leállt.</string> + <string name="trying_to_connect_to_server_to_receive_messages">Csatlakozási kísérlet a kapcsolat üzeneteinek fogadására használt kiszolgálóhoz ettől az ismerősödtől.</string> + <string name="la_could_not_be_verified">Nem sikerült ellenőrizni téged; kérjük, próbáld meg újra.</string> + <string name="moderate_message_will_be_marked_warning">Az üzenet minden tag számára moderáltként lesz megjelölve.</string> + <string name="enter_passphrase_notification_desc">Ha szeretnél értesítéseket kapni, kérjük, add meg az adatbázis jelszavát.</string> + <string name="error_smp_test_failed_at_step">A teszt a(z) %s lépésnél sikertelen volt.</string> + <string name="auth_you_will_be_required_to_authenticate_when_you_start_or_resume">Az alkalmazás indításakor, vagy 30 másodpercnyi háttérben töltött idő után az alkalmazáshoz visszatérve hitelesítened kell magad.</string> + <string name="moderate_message_will_be_deleted_warning">Az üzenet minden tag számára törlésre kerül.</string> + <string name="video_decoding_exception_desc">A videó nem dekódolható. Kérjük, próbálj meg egy másik videót, vagy lépj kapcsolatba a fejlesztőkkel.</string> + <string name="this_text_is_available_in_settings">Ez a szöveg a beállítások között érhető el</string> + <string name="profile_will_be_sent_to_contact_sending_link">A profilodat elküldjük annak az ismerősödnek, akitől ezt a linket kaptad.</string> + <string name="system_restricted_background_in_call_desc">Az alkalmazás 1 perc után bezárható a háttérben.</string> + <string name="group_preview_you_are_invited">meg lettél hívva a csoportba</string> + <string name="turn_off_battery_optimization"><![CDATA[Használatához kérjük, <b>engedélyezd a SimpleX háttérben történő futtatását</b> a következő párbeszédpanelen. Ellenkező esetben az értesítések le lesznek tiltva.]]></string> + <string name="error_smp_test_server_auth">A kiszolgálónak engedélyre van szüksége a várólisták létrehozásához, ellenőrízd a jelszavadat</string> + <string name="you_will_join_group">Csatlakozni fogsz a csoport összes tagjához.</string> + <string name="error_smp_test_certificate">Lehetséges, hogy a kiszolgáló címében szereplő tanúsítvány-ujjlenyomat helytelen</string> + <string name="la_notice_to_protect_your_information_turn_on_simplex_lock_you_will_be_prompted_to_complete_authentication_before_this_feature_is_enabled">Az adatok védelme érdekében kapcsold be a SimpleX Lock funkciót. +\nA funkció engedélyezése előtt a rendszer felszólít téged a hitelesítés befejezésére.</string> + <string name="video_will_be_received_when_contact_is_online">A videó akkor érkezik, amikor az ismerősöd elérhető, kérlek várj vagy nézd meg később!</string> + <string name="network_error_desc">Kérjük, ellenőrizd hálózati kapcsolatodat a(z) %1$s segítségével, és próbáld meg újra.</string> + <string name="you_can_turn_on_lock">A SimpleX Lock-ot a Beállításokon keresztül kapcsolhatod be.</string> + <string name="app_was_crashed">Az alkalmazás összeomlott</string> + <string name="please_check_correct_link_and_maybe_ask_for_a_new_one">Kérjük, ellenőrizd, hogy a megfelelő linket használtad-e, vagy kérd meg az ismerősödet, hogy küldjön egy másikat.</string> + <string name="image_decoding_exception_desc">A kép nem dekódolható. Kérjük, próbálj meg egy másik képet, vagy lépj kapcsolatba a fejlesztőkkel.</string> + <string name="non_content_uri_alert_text">Érvénytelen fájl elérési útvonalat osztottál meg. Jelentsd a problémát az alkalmazás fejlesztőinek.</string> + <string name="failed_to_create_user_duplicate_desc">Már van egy chat-profilod ugyanezzel a megjelenített névvel. Kérjük, válassz másik nevet.</string> + <string name="trying_to_connect_to_server_to_receive_messages_with_error">Csatlakozási kísérlet a kapcsolat üzeneteinek fogadására használt szerverhez ettől az ismerősödtől (hiba: %1$s).</string> + <string name="stop_rcv_file__message">A fájl fogadása leállt.</string> + <string name="la_please_remember_to_store_password">Kérjük, jegyezd meg vagy tárold biztonságosan - az elveszett jelszót nem lehet visszaállítani!</string> + <string name="video_will_be_received_when_contact_completes_uploading">A videó akkor érkezik meg, amikor az ismerősöd befejezi a feltöltést.</string> + <string name="description_you_shared_one_time_link_incognito">egyszeri linket osztottál meg inkognitóban</string> + <string name="connected_to_server_to_receive_messages_from_contact">Csatlakozol ahhoz a kiszolgálóhoz, amely az adott ismerősödtől érkező üzenetek fogadására szolgál.</string> + <string name="you_can_enable_delivery_receipts_later">Később engedélyezheted a Beállításokban</string> + <string name="you_will_be_connected_when_group_host_device_is_online">Csatlakozni fogsz a csoporthoz amikor a csoport tulajdonosának az eszköze online lesz. Kérlek várj vagy nézz vissza később!</string> + <string name="mtr_error_different">eltérő migráció az appban/adatbázisban: %s / %s</string> + <string name="connect_plan_you_are_already_connecting_to_vName"><![CDATA[Már kapcsolatban vagy vele: <b>%1$s</b>.]]></string> + <string name="unhide_profile">Profil felfedése</string> + <string name="this_link_is_not_a_valid_connection_link">Ez a link nem érvényes meghívó link!</string> + <string name="to_verify_compare">A felek közötti titkosítás (e2e) ellenőrzéséhez hasonlítsd össze (vagy olvasd be) a kódot az ismerősöddel együtt az eszközeiteken!</string> + <string name="you_must_use_the_most_recent_version_of_database">A csevegési adatbázis legfrissebb verzióját CSAK egy eszközön kell használnod, ellenkező esetben előfordulhat, hogy az üzeneteket nem fogod megkapni valamennyi kapcsolatodtól.</string> + <string name="messages_section_description">Ez a beállítás a jelenlegi chat profilodban lévő üzenetekre érvényes</string> + <string name="you_are_invited_to_group_join_to_connect_with_group_members">Meg vagy hívva a csoportba. Csatlakozz és lépj kapcsolatba a csoporttagokkal!</string> + <string name="alert_message_no_group">Ez a csoport többé nem létezik.</string> + <string name="connect_plan_you_are_already_joining_the_group_via_this_link">A csatlakozásod már folyamatban van a csoporthoz ezzel a linkkel!</string> + <string name="you_are_invited_to_group">Meg vagy hívva a csoportba</string> + <string name="contact_sent_large_file">Az ismerősöd a jelenleg megengedett maximális méretű (%1$s) fájlnál nagyobbat küldött.</string> + <string name="we_do_not_store_contacts_or_messages_on_servers">Nem tároljuk egyetlen üzenetedet illetve ismerőseidet (kézbesítás után) a SimpleX szervereken.</string> + <string name="you_can_use_markdown_to_format_messages__prompt">Üzenetek formázása a szövegbe szúrt speciális karakterekkel:</string> + <string name="you_can_also_connect_by_clicking_the_link"><![CDATA[A linkre kattintással is kapcsolódhatsz. Ha megnyílik böngészőben, kattints a<b>Mobil appban megnyitás</b> gombra.]]></string> + <string name="your_chat_profile_will_be_sent_to_your_contact">A chat profilod megküldésre kerül +\naz ismerősöd számára</string> + <string name="invite_prohibited_description">Egy olyan ismerőst próbálsz meghívni, akivel inkognító profilt osztottál meg abban a csoportban, amelyben a saját fő profilodat használod</string> + <string name="connect_plan_you_are_already_joining_the_group_vName"><![CDATA[Már folyamatban van a csatlakozásod a(z) <b>%1$s</b> csoporthoz.]]></string> + <string name="onboarding_notifications_mode_off">Amikor az app fut</string> + <string name="alert_title_cant_invite_contacts_descr">Inkognító profilt használsz ehhez a csoporthoz - a fő profilod megosztásának elkerülése érdekében meghívók küldése tiltott</string> + <string name="v4_5_transport_isolation">Kapcsolat izolációs mód</string> + <string name="you_will_be_connected_when_your_connection_request_is_accepted">Csatlakoztok amikor a meghívód elfogadásra kerül. Kérlek várj vagy nézz vissza később!</string> + <string name="voice_messages_are_prohibited">A hangüzenetek küldése le van tiltva ebben a csoportban.</string> + <string name="system_restricted_background_in_call_warn"><![CDATA[A háttérben való hívásokhoz kérlek válaszd az <b>App akkumulátor használat</b> / <b>Korlátlan</b> módot az app beállításaiban.]]></string> + <string name="v5_4_link_mobile_desktop_descr">Biztonságos kvantum ellenálló protokoll által.</string> + <string name="v5_1_better_messages_descr">- hangüzenetek 5 percig. +\n- egyedi eltűnési időhatár +\n- előzmény szerkesztése</string> + <string name="open_on_mobile_and_scan_qr_code"><![CDATA[Kattints a <i>Használd a számítógépről</i> gombra a mobil appban és olvasd be a QR-kódot!]]></string> + <string name="sender_at_ts">%s at %s</string> + <string name="you_will_be_connected_when_your_contacts_device_is_online">Csatlakoztok amikor az ismerősöd eszköze online lesz. Kérlek várj vagy nézz vissza később!</string> + <string name="v5_4_block_group_members_descr">Kéretlen üzenetek elrejtése.</string> + <string name="disable_onion_hosts_when_not_supported"><![CDATA[Állítsd a <i>Használd az .onion hostokat</i> NEM-re ha a SOCKS proxy nem támogatja.]]></string> + <string name="you_can_share_your_address">Megoszthatod a SimpleX azonosítódat linkben vagy QR-kódban - bárki kapcsolatfelvételt kezdeményezhet veled.</string> + <string name="you_can_create_it_later">Később létrehozhatod</string> + <string name="your_profile_is_stored_on_device_and_shared_only_with_contacts_simplex_cannot_see_it">A profilod a te eszközödön van tárolva és csak az ismerőseiddel kerül megosztásra! A SimpleX chat szerverek nem láthatják a profilodat!</string> + <string name="snd_group_event_changed_member_role">%s szerepkörét megváltoztattad erre: %s</string> + <string name="you_rejected_group_invitation">Elutasítottad a meghívót a csoportba</string> + <string name="to_protect_privacy_simplex_has_ids_for_queues">Az adatvédelem érdekében, a más chat platformokon megszokott felhasználói azonosítók helyett, a SimpleX üzenetsorokhoz rendel azonosítókat, minden egyes ismerősödhöz egy különbözőt.</string> + <string name="to_share_with_your_contact">(megosztás az ismerősöddel)</string> + <string name="you_sent_group_invitation">Csoport meghívót küldtél</string> + <string name="update_network_session_mode_question">Kapcsolat izolációs mód frissítése?</string> + <string name="network_session_mode_transport_isolation">Kapcsolat izolációs mód</string> + <string name="you_will_stop_receiving_messages_from_this_group_chat_history_will_be_preserved">Ettől a csoporttól nem fogsz értesítéseket kapni. A chat előzmény megmarad.</string> + <string name="database_is_not_encrypted">A chat adatbázisod nem titkosított - állíts be jelmondatot a megvédéséhez!</string> + <string name="network_disable_socks">Közvetlen internet kapcsolat használata?</string> + <string name="you_will_still_receive_calls_and_ntfs">Továbbra is kapsz hívásokat és értesítéseket az elnémított profilokból amikor azok aktívak.</string> + <string name="group_main_profile_sent">A saját fő chat profilod megküldésre kerül a csoporttagok számára.</string> + <string name="you_can_enable_delivery_receipts_later_alert">Később engedélyezheted az alkalmazás Adatvédelmi és Biztonsági beállításaiban.</string> + <string name="to_reveal_profile_enter_password">A rejtett profilod felfedéséhez gépeld be a jelszót a kereső mezőbe a Chat profiljaid oldalon!</string> + <string name="upgrade_and_open_chat">A chat frissítése és megnyitása</string> + <string name="you_need_to_allow_to_send_voice">Ahhoz, hogy hangüzeneteket küldhess, engedélyezned kell az ismerőseidnek is azok küldését.</string> + <string name="you_control_servers_to_receive_your_contacts_to_send"><![CDATA[Te kontrollálod, hogy melyik szerveren(-ken) keresztül <b>fogadod</b>az üzeneteket, míg az ismerőseid a szervereket amelyeken át üzensz nekik.]]></string> + <string name="connect_plan_you_are_already_in_group_vName"><![CDATA[Már a(z) <b>%1$s</b> csoportban vagy.]]></string> + <string name="snd_conn_event_switch_queue_phase_completed">megváltoztattad az azonosítót</string> + <string name="v4_3_irreversible_message_deletion_desc">Az ismerőseid engedélyezhetik a teljes üzenet törlést.</string> + <string name="you_have_to_enter_passphrase_every_time">Be kell írd a jelmondatodat a SimpleX app minden indulásakor - nem az eszközön lesz tárolva.</string> + <string name="open_port_in_firewall_desc">Ahhoz, hogy engedélyezd a mobil app csatlakozását a számítógépedhez, nyisd meg ezt a portot a tűzfaladon, ha az engedélyezve van</string> + <string name="your_profile_is_stored_on_your_device">A te profilod, ismerőseid és az elküldött üzeneteid a te eszközödön vannak tárolva (a SimpleX chat szerverekről kézbesítés illetve a TTL időkorlát után törlődnek).</string> + <string name="system_restricted_background_warn"><![CDATA[Az értesítések engedélyezéséhez kérlek válaszd az <b>App akkumulátor használat</b> / <b>Korlátlan</b> módot az app beállításaiban.]]></string> + <string name="this_string_is_not_a_connection_link">Ez a karakterlánc nem meghívó link!</string> + <string name="to_start_a_new_chat_help_header">Új chat kezdése</string> + <string name="connect_plan_you_are_already_connecting_via_this_one_time_link">Csatlakozásod már folyamatban van ezzel az Egyszer használatos link-el!</string> + <string name="you_wont_lose_your_contacts_if_delete_address">Nem fogod elveszíteni az ismerőseidet ha később törlöd a SimpleX azonosítódat.</string> + <string name="updating_settings_will_reconnect_client_to_all_servers">A beállítások frissítése a szerverekhez újra kapcsolódással jár.</string> + <string name="contact_wants_to_connect_with_you">kapcsolatba akar lépni veled!</string> + <string name="snd_group_event_changed_role_for_yourself">a saját szerepkörödet megváltoztattad erre: %s</string> + <string name="you_can_start_chat_via_setting_or_by_restarting_the_app">A chat szolgáltatást elindíthatod a beállítások / adatbázis pontban vagy az app újraindításával.</string> + <string name="verify_code_on_mobile">Ellenőrizd a kódot a mobilon!</string> + <string name="youve_accepted_group_invitation_connecting_to_inviting_group_member">Csatlakoztál ehhez a csoporthoz. Kapcsolódás a meghívó csoporttaghoz.</string> + <string name="you_can_connect_to_simplex_chat_founder"><![CDATA[Kapcsolatba léphetsz <font color="#0088ff">a SimpleX Chat fejlesztőivel és kérdezhetsz bármit és értesülhetsz az újdonságokról</font>.]]></string> + <string name="v4_2_auto_accept_contact_requests_desc">Opcionális üdvözlő üzenettel.</string> + <string name="unknown_database_error_with_info">Ismeretlen adatbázis hiba: %s</string> + <string name="you_can_hide_or_mute_user_profile">Elrejtheted vagy némíthatod egy felhasználó profilját - tartsd lenyomva a menühöz!</string> + <string name="v5_3_simpler_incognito_mode_descr">Inkognító mód csatlakozáskor</string> + <string name="update_onion_hosts_settings_question">TOR .onion host beállítások frissítése?</string> + <string name="you_can_share_group_link_anybody_will_be_able_to_connect">Megoszthatsz egy linket vagy QR-kódot - így bárki csatlakozhat a csoporthoz. Csoporttagokat nem fogsz elveszíteni, az esetben sem ha kásőbb törlöd a csoportot.</string> + <string name="you_joined_this_group">Csatlakoztál ehhez a csoporthoz</string> + <string name="connect_plan_this_is_your_link_for_group_vName"><![CDATA[Ez a linked a(z) <b>%1$s</b> csoporthoz!]]></string> + <string name="voice_prohibited_in_this_chat">A hangüzenetek le vannak tiltva ebben a csevegésben.</string> + <string name="you_control_your_chat">Te tartod kézben chatedet!</string> + <string name="verify_code_with_desktop">Kód ellenőrzése a számítógépen</string> + <string name="v4_5_private_filenames_descr">Az időzóna, kép/hang fájlok megvédése érdekében használd az UTC-t!</string> + <string name="connect_via_member_address_alert_desc">A meghívó elküldésre kerül a csoporttag számára.</string> + <string name="incognito_info_share">Amikor megosztasz egy inkognító profilt valakivel, az a profil lesz használva a csoporthoz is amibe meghív.</string> + <string name="connect_plan_you_have_already_requested_connection_via_this_address">Már küldtél meghívót ezen az azonosítón keresztül!</string> + <string name="you_can_share_this_address_with_your_contacts">Megoszthatod ezt a SimpleX azonosítót az ismerőseiddel, hogy kapcsolatba léphessenek %s-el .</string> + <string name="you_can_accept_or_reject_connection">Amikor meghívót kapsz emberektől, elfogadhatod vagy elutasíthatod azokat!</string> + <string name="v4_6_group_welcome_message_descr">Állítsd be az új tagoknak megjelenő üzenetet!</string> + <string name="whats_new_thanks_to_users_contribute_weblate">Köszönet a felhasználóknak - hozzájárulás a Weblaten!</string> + <string name="sending_delivery_receipts_will_be_enabled">A kézbesítési jelentés küldése minden kapcsolat számára engedélyezve lesz.</string> + <string name="network_option_protocol_timeout_per_kb">Protokoll időkorlát KB-onként</string> + <string name="database_backup_can_be_restored">Az adatbázis jelmondatának megváltoztatására tett kísérlet nem fejeződött be.</string> + <string name="enable_automatic_deletion_message">Ez a művelet nem vonható vissza - a kiválasztottnál korábban küldött és fogadott üzenetek törlésre kerülnek. Ez több percet is igénybe vehet.</string> + <string name="profile_is_only_shared_with_your_contacts">A profilod csak az ismerőseid számára kerül megosztásra.</string> + <string name="smp_servers_test_some_failed">Néhány szerver megbukott a teszten:</string> + <string name="group_invitation_tap_to_join">Érintsd meg a csatlakozáshoz</string> + <string name="delete_files_and_media_desc">Ez a művelet nem vonható vissza - az összes fogadott és küldött fájl a médiatartalommal együtt törlésre kerülnek. Az alacsony felbontású fotók viszont megmaradnak.</string> + <string name="receipts_contacts_override_enabled">A kézbesítési jelentés engedélyezve van %d ismerősödnél</string> + <string name="sending_via">Küldés ezen keresztül:</string> + <string name="v5_0_polish_interface_descr">Köszönet a felhasználóknak - hozzájárulás a Weblaten!</string> + <string name="sending_delivery_receipts_will_be_enabled_all_profiles">A kézbesítési jelentés küldése az összes látható csevegőprofilban lévő összes ismerős számára engedélyezve lesz.</string> + <string name="v4_6_audio_video_calls_descr">Bluetooth támogatás és egyéb fejlesztések.</string> + <string name="in_developing_desc">Ez a funkció még nem támogatott. Próbáld meg a következő kiadásban.</string> + <string name="share_text_updated_at">A bejegyzés frissítve: %s</string> + <string name="skip_inviting_button">Tagok meghívásának kihagyása</string> + <string name="receipts_section_description_1">Ezek felülbírálhatóak az ismerős- és csoportbeállításokban.</string> + <string name="contact_you_shared_link_with_wont_be_able_to_connect">Az ismerős, akivel megosztottad ezt a linket, NEM fog tudni csatlakozni!</string> + <string name="you_can_change_it_later">A véletlenszerű jelmondat egyszerű szövegként van tárolva a beállításokban. +\nKésőbb megváltoztathatod.</string> + <string name="group_invitation_tap_to_join_incognito">Érintsd meg az inkognitóban való csatlakozáshoz</string> + <string name="set_password_to_export">Jelmondat beállítása az exportáláshoz</string> + <string name="receipts_groups_override_disabled">Az üzenet kézbesítési jelentés le van tiltva %d csoportnál</string> + <string name="non_fatal_errors_occured_during_import">Néhány nem végzetes hiba történt az importálás során - további részletekért lásd a Chat-konzolt.</string> + <string name="v4_5_italian_interface_descr">Köszönet a felhasználóknak - hozzájárulás a Weblaten!</string> + <string name="relay_server_if_necessary">A relé szerver csak végszükség esetén használatos. Egy másik fél megfigyelheti az IP-címedet.</string> + <string name="v5_0_app_passcode_descr">Állítsd be a rendszerhitelesítés helyett.</string> + <string name="switch_receiving_address_desc">A fogadó cím egy másik szerverre változik. A címváltoztatás a feladó online állapotba kerülése után fejeződik be.</string> + <string name="stop_chat_to_export_import_or_delete_chat_database">A csevegés leállítása a csevegőadatbázis exportálásához, importálásához vagy törléséhez. A csevegés leállítása alatt nem tudsz üzeneteket fogadni és küldeni.</string> + <string name="save_passphrase_in_keychain">Jelmondat mentése a Kulcstárban</string> + <string name="v4_6_chinese_spanish_interface_descr">Köszönet a felhasználóknak - hozzájárulás a Weblaten!</string> + <string name="save_passphrase_in_settings">Jelmondat mentése a beállításokban</string> + <string name="send_receipts_disabled_alert_msg">Ennek a csoportnak több mint %1$d tagja van, a kézbesítési jelentések nem kerülnek elküldésre.</string> + <string name="v5_2_message_delivery_receipts_descr">A második jelölés, amit kihagytunk! ✅</string> + <string name="relay_server_protects_ip">A relay szerver védi az IP-címedet, de megfigyelheti a hívás időtartamát.</string> + <string name="read_more_in_github">További információ a GitHub tárolónkban.</string> + <string name="v4_5_message_draft_descr">Az utolsó üzenet tervezetének megőrzése a mellékletekkel együtt.</string> + <string name="saved_ICE_servers_will_be_removed">A mentett WebRTC ICE-kiszolgálók eltávolításra kerülnek.</string> + <string name="receipts_groups_override_enabled">A kézbesítési jelentés engedélyezve van %d csoportnál</string> + <string name="member_role_will_be_changed_with_notification">A szerepkör \"%s\"-re fog változni. A csoportban mindenki értesítést kap.</string> + <string name="users_delete_with_connections">Profil és szerverkapcsolatok</string> + <string name="the_messaging_and_app_platform_protecting_your_privacy_and_security">A Te adatvédelmedet és biztonságodat védő üzenetküldő és alkalmazásplatform.</string> + <string name="tap_to_activate_profile">Érintsd meg a profil aktiválásához.</string> + <string name="receipts_contacts_override_disabled">Az üzenet kézbesítési jelentés le van tiltva %d ismerősödnél</string> + <string name="session_code">Munkamenet kód</string> + <string name="v4_4_french_interface_descr">Köszönet a felhasználóknak - hozzájárulás a Weblaten!</string> + <string name="receipts_section_groups">Kis csoportok (max. 20 tag)</string> + <string name="connection_you_accepted_will_be_cancelled">Az általad elfogadott kapcsolat törlésre kerül!</string> + <string name="send_live_message_desc">Élő üzenet küldése - a címzett(ek) számára frissül, miközben írod az üzenetet.</string> + <string name="settings_section_title_delivery_receipts">A KÉZBESÍTÉSI JELENTÉSEKET A KÖVETKEZŐ CÍMRE KELL KÜLDENI</string> + <string name="alert_text_msg_bad_id">A következő üzenet azonosítója hibás (kisebb vagy egyenlő az előzővel). +\nEz valamilyen hiba, vagy sérült kapcsolat esetén fordulhat elő.</string> + <string name="this_device_name_shared_with_mobile">Az eszköz neve megosztásra kerül a csatlakoztatott mobil klienssel.</string> + <string name="v4_4_live_messages_desc">A címzettek a beírás közben látják a frissítéseket.</string> + <string name="store_passphrase_securely">Kérjük, hogy a jelmondatot biztonságosan tárold, ha elveszíted, NEM tudod megváltoztatni.</string> + <string name="passphrase_will_be_saved_in_settings">A jelmondat a beállításokban egyszerű szövegként tárolódik, miután megváltoztattad vagy újraindítottad az alkalmazást.</string> + <string name="smp_servers_per_user">Jelenlenlegi profilod új ismerőseinek kiszolgálói</string> + <string name="receiving_via">Fogadás a</string> + <string name="store_passphrase_securely_without_recover">Kérjük, hogy a jelmondatot biztonságosan tárold, ha elveszíted, NEM fogsz tudni hozzáférni a chathez.</string> + <string name="member_role_will_be_changed_with_invitation">A szerepkör \"%s\"-re fog változni. A tag új meghívót kap.</string> + <string name="icon_descr_profile_image_placeholder">profilkép helyőrző</string> + <string name="sync_connection_force_desc">A titkosítás működik, és új titkosítási egyezményre nincs szükség. Ez kapcsolati hibákat eredményezhet!</string> + <string name="delete_chat_profile_action_cannot_be_undone_warning">Ez a művelet nem vonható vissza - profilod, ismerőseid, üzeneteid és fájljaid visszafordíthatatlanul törlésre kerülnek.</string> + <string name="info_row_updated_at">A bejegyzés frissítve</string> + <string name="read_more_in_user_guide_with_link"><![CDATA[További információ a <font color="#0088ff">Felhasználói útmutatóban</font> olvasható.]]></string> + <string name="settings_is_storing_in_clear_text">A jelmondat a beállításokban egyszerű szövegként van tárolva.</string> + <string name="terminal_always_visible">Konzol megjelenítése új ablakban</string> + <string name="alert_text_msg_bad_hash">Az előző üzenet hash-e más.</string> + <string name="receipts_section_description">Ezek a beállítások a jelenlegi profilodra vonatkoznak</string> + <string name="loading_remote_file_desc">Kérjük, várj, amíg a fájl betöltődik az összekapcsolt mobilról.</string> + <string name="read_more_in_github_with_link"><![CDATA[További információ a <font color="#0088ff">GitHub tárolónkban</font>.]]></string> + <string name="error_showing_content">hiba a tartalom megjelenítése közben</string> + <string name="error_showing_message">hiba az üzenet megjelenítésekor</string> + <string name="you_can_make_address_visible_via_settings">Láthatóvá teheted a SimpleX ismerőseid számára a Beállításokban.</string> + <string name="recent_history_is_sent_to_new_members">Legfeljebb az utolsó 100 üzenet kerül elküldésre az új tagoknak.</string> + <string name="code_you_scanned_is_not_simplex_link_qr_code">A beolvasott kód nem egy SimpleX link QR-kód.</string> + <string name="the_text_you_pasted_is_not_a_link">A beillesztett szöveg nem SimpleX link.</string> + <string name="you_can_view_invitation_link_again">A meghívó linket újra megtekintheti a kapcsolat részletei között.</string> + <string name="start_chat_question">Csevegés indítása?</string> + <string name="recent_history">Látható előzmények</string> + <string name="la_app_passcode">Alkalmazás jelkód</string> + <string name="add_contact_tab">Kapcsolat hozzáadása</string> + <string name="tap_to_scan">Koppints a beolvasáshoz</string> + <string name="tap_to_paste_link">Koppints a hivatkozás beillesztéséhez</string> + <string name="add_contact_button_to_create_link_or_connect_via_link"><![CDATA[<b>Ismerős hozzáadása</b>: új meghívó link létrehozásához, vagy egy kapott linken keresztül történő csatlakozáshoz.]]></string> + <string name="create_group_button_to_create_new_group"><![CDATA[<b>Új csoport létrehozása</b>: új csoport létrehozásához.]]></string> + <string name="chat_is_stopped_you_should_transfer_database">A csevegés leállt. Ha már használtad ezt az adatbázist egy másik eszközön, a csevegés megkezdése előtt vissza kell állítanod.</string> + <string name="recent_history_is_not_sent_to_new_members">Az előzmények nem kerülnek elküldésre új tagok részére.</string> + <string name="retry_verb">Újrapróbálkozás</string> + <string name="camera_not_available">A kamera nem elérhető</string> + <string name="enable_sending_recent_history">Utolsó 100 üzenet küldése új tagoknak.</string> + <string name="disable_sending_recent_history">Ne küldjön előzményeket új tagoknak.</string> + <string name="or_show_this_qr_code">Vagy mutassa meg ezt a kódot</string> + <string name="enable_camera_access">Kamera hozzáférés engedélyezése</string> + <string name="keep_unused_invitation_question">Megtartod a fel nem használt meghívót?</string> + <string name="share_this_1_time_link">Egyszer használatos link megosztása</string> + <string name="new_chat">Új beszélgetés</string> + <string name="loading_chats">Csevegések betöltése…</string> + <string name="creating_link">Link létrehozása…</string> + <string name="or_scan_qr_code">Vagy QR-kód beolvasása</string> + <string name="invalid_qr_code">Érvénytelen QR-kód</string> + <string name="keep_invitation_link">Megtart</string> + <string name="search_or_paste_simplex_link">Keresés vagy SimpleX link beillesztése</string> + <string name="show_internal_errors">Belső hibák megjelenítése</string> + <string name="agent_critical_error_title">Kritikus hiba</string> + <string name="agent_internal_error_title">Belső hiba</string> + <string name="remote_ctrl_error_bad_version">Az asztali kliens verziója nem támogatott. Kérlek, győződj meg arról, hogy mindkét eszközön ugyanazt a verziót használod</string> + <string name="remote_ctrl_error_bad_invitation">Az asztali kliensen hibás meghívókód szerepel</string> + <string name="remote_ctrl_error_busy">Az asztali kliens elfoglalt</string> + <string name="remote_ctrl_error_inactive">Az asztali kliens inaktív</string> + <string name="restart_chat_button">Csevegés újraindítása</string> + <string name="remote_ctrl_error_timeout">Időtúllépés az asztali klienshez való kapcsolódás közben</string> + <string name="remote_ctrl_error_disconnected">Az asztali kliens kapcsolata megszakadt</string> + <string name="remote_host_was_disconnected_title">A kapcsolat megszakadt</string> + <string name="remote_ctrl_was_disconnected_title">A kapcsolat megszakadt</string> + <string name="remote_ctrl_error_bad_state">Az asztali kliens kapcsolata rossz állapotban van</string> + <string name="agent_critical_error_desc">Kérjük, jelezd ezt a fejlesztőknek: +\n%s +\n +\nJavasoljuk, hogy indítsd újra az alkalmazást.</string> + <string name="agent_internal_error_desc">Kérjük, jelezd a fejlesztőknek: +\n%s</string> + <string name="remote_host_error_bad_version"><![CDATA[A(z) <b>%s</b> mobil eszköz verziója nem támogatott. Kérlek, győződj meg róla, hogy mindkét eszközön ugyanazt a verziót használod]]></string> + <string name="remote_host_error_disconnected"><![CDATA[Megszakadt a kapcsolat a(z) <b>%s</b> mobil eszközzel]]></string> + <string name="failed_to_create_user_invalid_title">Érvénytelen megjelenítendő felhaszálónév!</string> + <string name="failed_to_create_user_invalid_desc">Ez a megjelenített felhasználónév érvénytelen. Kérjük, válassz másikat.</string> + <string name="remote_host_disconnected_from"><![CDATA[Megszakadt a kapcsolat a <b>%s</b> mobil eszközzel, a(z) %s probléma miatt.]]></string> + <string name="remote_ctrl_disconnected_with_reason">%s probléma miatt megszakadt a kapcsolat</string> + <string name="remote_host_error_missing"><![CDATA[A(z) <b>%s</b> mobil eszköz nem található]]></string> + <string name="remote_host_error_bad_state"><![CDATA[A kapcsolat a(z) <b>%s</b> mobil eszközzel rossz állapotban van]]></string> + <string name="remote_host_error_timeout"><![CDATA[Időtúllépés a(z) <b>%s</b> mobil eszközhöz való csatlakozás közben]]></string> + <string name="group_member_status_unknown_short">ismeretlen</string> + <string name="possible_slow_function_title">Lassú funkció</string> + <string name="show_slow_api_calls">Lassú API-hívások megjelenítése</string> + <string name="remote_host_error_inactive"><![CDATA[A(z) <b>%s</b> mobil eszköz inaktív]]></string> + <string name="possible_deadlock_title">Elakadt</string> + <string name="developer_options_section">Fejlesztői beállítások</string> + <string name="possible_deadlock_desc">A kód végrehajtása túl sokáig tart: %1$d másodperc. Valószínűleg az alkalmazás lefagyott: %2$s</string> + <string name="possible_slow_function_desc">A funkció végrehajtása túl sokáig tart: %1$d másodperc: %2$s</string> + <string name="remote_host_error_busy"><![CDATA[A(z) <b>%s</b> mobil eszköz elfoglalt]]></string> + <string name="past_member_vName">Legutóbbi tag %1$s</string> + <string name="group_member_status_unknown">ismeretlen státusz</string> + <string name="profile_update_event_member_name_changed">%1$s tag %2$s-ra/re változott</string> + <string name="profile_update_event_removed_address">törölt csatlakozási cím</string> + <string name="profile_update_event_removed_picture">törölt profilkép</string> + <string name="profile_update_event_set_new_address">új kapcsolattartási cím beállítása</string> + <string name="profile_update_event_set_new_picture">új profilkép beállítása</string> + <string name="profile_update_event_updated_profile">frissített profil</string> + <string name="profile_update_event_contact_name_changed">%1$s ismerős %2$s-ra/re változott</string> + <string name="note_folder_local_display_name">Privát jegyzetek</string> + <string name="error_deleting_note_folder">Hiba a privát jegyzetek törlésekor</string> + <string name="error_creating_message">Hiba az üzenet létrehozásakor</string> + <string name="clear_note_folder_question">Törlöd a privát jegyzeteket?</string> + <string name="info_row_created_at">Létrehozva ekkor:</string> + <string name="saved_message_title">Mentett üzenet</string> + <string name="share_text_created_at">Létrehozva ekkor: %s</string> + <string name="clear_note_folder_warning">Az összes üzenet törlődik – ez nem vonható vissza!</string> + <string name="v5_5_message_delivery">Továbbfejlesztett üzenetküldés</string> + <string name="v5_5_join_group_conversation">Csatlakozás csoportos beszélgetésekhez</string> + <string name="v5_5_simpler_connect_ui">A link beillesztése a csatlakozáshoz!</string> + <string name="v5_5_private_notes">Privát jegyzetek</string> + <string name="v5_5_simpler_connect_ui_descr">A keresősáv fogadja a meghívó hivatkozásokat.</string> + <string name="v5_5_private_notes_descr">Titkosított fájlokkal és médiatartalommal.</string> + <string name="v5_5_message_delivery_descr">Csökkentett akkumulátorhasználattal.</string> + <string name="v5_5_new_interface_languages">Magyar és török felhasználói felület</string> + <string name="v5_5_join_group_conversation_descr">A közelmúlt eseményei és továbbfejlesztett Jegyzék Bot.</string> + <string name="rcv_group_event_member_unblocked">%s letiltása feloldva</string> + <string name="snd_group_event_member_unblocked">feloldottad %s letiltását</string> + <string name="member_info_member_blocked">letiltva</string> + <string name="blocked_by_admin_item_description">letiltva az admin által</string> + <string name="member_blocked_by_admin">Letiltva az admin által</string> + <string name="rcv_group_event_member_blocked">%s letiltva</string> + <string name="block_for_all">Mindenki számára letiltva</string> + <string name="block_for_all_question">Mindenki számára letiltod ezt a tagot?</string> + <string name="blocked_by_admin_items_description">%d üzenet letiltva az admin által</string> + <string name="unblock_for_all">Letiltás feloldása mindenki számára</string> + <string name="unblock_for_all_question">Mindenki számára feloldod ennek a tagnak a letiltását?</string> + <string name="snd_group_event_member_blocked">letiltottad %s-t</string> + <string name="error_blocking_member_for_all">Hiba a tag mindenki számára való letiltása során</string> </resources> \ No newline at end of file diff --git a/apps/multiplatform/common/src/commonMain/resources/MR/images/ic_avg_pace.svg b/apps/multiplatform/common/src/commonMain/resources/MR/images/ic_avg_pace.svg new file mode 100644 index 0000000000..d3052a6c84 --- /dev/null +++ b/apps/multiplatform/common/src/commonMain/resources/MR/images/ic_avg_pace.svg @@ -0,0 +1 @@ +<svg xmlns="http://www.w3.org/2000/svg" height="24" viewBox="0 -960 960 960" width="24"><path d="M609.824-771.5q-15.824 0-27.074-11.426-11.25-11.426-11.25-27.25t11.426-27.324q11.426-11.5 27.25-11.5t27.324 11.676q11.5 11.676 11.5 27.5t-11.676 27.074q-11.676 11.25-27.5 11.25Zm0 660q-15.824 0-27.074-11.426-11.25-11.426-11.25-27.25t11.426-27.324q11.426-11.5 27.25-11.5t27.324 11.676q11.5 11.676 11.5 27.5t-11.676 27.074q-11.676 11.25-27.5 11.25Zm160-520q-15.824 0-27.074-11.426-11.25-11.426-11.25-27.25t11.426-27.324q11.426-11.5 27.25-11.5t27.324 11.676q11.5 11.676 11.5 27.5t-11.676 27.074q-11.676 11.25-27.5 11.25Zm0 380q-15.824 0-27.074-11.426-11.25-11.426-11.25-27.25t11.426-27.324q11.426-11.5 27.25-11.5t27.324 11.676q11.5 11.676 11.5 27.5t-11.676 27.074q-11.676 11.25-27.5 11.25Zm60-190q-15.824 0-27.074-11.426-11.25-11.426-11.25-27.25t11.426-27.324q11.426-11.5 27.25-11.5t27.324 11.676q11.5 11.676 11.5 27.5t-11.676 27.074q-11.676 11.25-27.5 11.25ZM480-81.5q-82.481 0-155.275-31.304-72.794-31.305-126.706-85.219-53.913-53.915-85.216-126.711Q81.5-397.531 81.5-480.016q0-82.484 31.303-155.273 31.303-72.79 85.216-126.699 53.912-53.909 126.706-85.461Q397.519-879 480-879v60q-141.5 0-240 98.562Q141.5-621.875 141.5-480t98.312 240.188Q338.125-141.5 480-141.5v60Zm-.111-330q-28.389 0-48.389-20.078-20-20.078-20-48.422 0-5.938.75-12.441.75-6.503 3.25-11.808L336-584l40-40.5 81.023 79.5q4.477-2 22.977-4 28.344 0 48.672 20.361Q549-508.279 549-479.889q0 28.389-20.361 48.389-20.36 20-48.75 20Z"/></svg> \ No newline at end of file diff --git a/apps/multiplatform/common/src/commonMain/resources/MR/images/ic_folder_filled.svg b/apps/multiplatform/common/src/commonMain/resources/MR/images/ic_folder_filled.svg new file mode 100644 index 0000000000..f4c284a5f2 --- /dev/null +++ b/apps/multiplatform/common/src/commonMain/resources/MR/images/ic_folder_filled.svg @@ -0,0 +1,18 @@ +<?xml version="1.0" encoding="UTF-8" standalone="no"?> +<svg + height="24" + viewBox="0 -960 960 960" + width="24" + xmlns="http://www.w3.org/2000/svg"> + <path + id="path151" + style="display:inline;fill:#ffffff;stroke-width:58" + d="M 480,-880 A 400,400 0 0 0 80,-480 400,400 0 0 0 480,-80 400,400 0 0 0 880,-480 400,400 0 0 0 480,-880 Z m -194.65461,218.29769 h 162.0477 l 33.18257,33.18257 h 194.07895 c 8.44741,0 16.07203,3.40719 22.90296,10.23849 6.83129,6.83091 10.2796,14.49667 10.2796,22.94408 v 263.85691 c 0,8.44742 -3.44831,16.07205 -10.2796,22.90295 -6.83093,6.83132 -14.45555,10.27962 -22.90296,10.27962 H 285.34539 c -8.83193,0 -16.59324,-3.4483 -23.23191,-10.27962 -6.63903,-6.8309 -9.95065,-14.45553 -9.95065,-22.90295 v -297.03948 c 0,-8.44742 3.31162,-16.07205 9.95065,-22.90295 6.63867,-6.83132 14.39998,-10.27962 23.23191,-10.27962 z" /> + <rect + style="font-variation-settings:normal;opacity:1;vector-effect:none;fill:#ffffff;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:19.9532;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;stop-color:#000000;stop-opacity:1" + id="rect151" + width="500" + height="30" + x="220" + y="-540" /> +</svg> diff --git a/apps/multiplatform/common/src/commonMain/resources/MR/images/ic_folder_pen.svg b/apps/multiplatform/common/src/commonMain/resources/MR/images/ic_folder_pen.svg new file mode 100644 index 0000000000..f1aba5bee6 --- /dev/null +++ b/apps/multiplatform/common/src/commonMain/resources/MR/images/ic_folder_pen.svg @@ -0,0 +1 @@ +<svg xmlns="http://www.w3.org/2000/svg" height="24" viewBox="0 -960 960 960" width="24"><path d="M142.5-222.5v-515 515Zm0 57.5q-22.969 0-40.234-17.266Q85-199.531 85-222.5v-515q0-22.969 17.266-40.234Q119.531-795 142.5-795h257q11.943 0 22.766 4.739 10.823 4.739 18.727 12.754L481-737.5h336.5q22.969 0 40.234 17.266Q875-702.969 875-680v193.5q-13.5-7.5-27.672-10.5t-29.828-3.5V-680H457l-57.5-57.5h-257v515h358-.5v57.5H142.5Zm415 51v-81q0-5.013 2-9.964 2-4.95 6.5-10.036l211.612-210.773q9.113-8.62 20.004-12.674 10.891-4.053 21.645-4.053 11.732 0 22.485 4.25Q852.5-434 861.5-425l37 37q8.765 8.855 12.632 19.677Q915-357.5 915-346.75t-4.382 22.031q-4.383 11.281-13.201 19.843L687.5-93.5q-5.086 4.5-9.949 6.5-4.864 2-10.051 2h-81q-12.25 0-20.625-8.375T557.5-114Zm299-233-37-37 37 37Zm-240 203h37.761L776.5-267l-17.887-19-18.88-18L616.5-182v38Zm142-142-19-18 37 37-18-19Z"/></svg> \ No newline at end of file diff --git a/apps/multiplatform/common/src/commonMain/resources/MR/images/ic_forum.svg b/apps/multiplatform/common/src/commonMain/resources/MR/images/ic_forum.svg new file mode 100644 index 0000000000..0f556da867 --- /dev/null +++ b/apps/multiplatform/common/src/commonMain/resources/MR/images/ic_forum.svg @@ -0,0 +1 @@ +<svg xmlns="http://www.w3.org/2000/svg" height="24" viewBox="0 -960 960 960" width="24"><path d="M283-245.5q-14 0-27.25-13.75T242.5-287v-98H735v-333.5h100q14 0 26.75 14T874.5-676v517.5q0 19.5-17.75 26.5t-31.25-6.5l-107-107H283Zm-40.5-197-108 108Q121-321 103.25-328T85.5-354.5V-834q0-14 12.75-27.75T125-875.5h512q14.5 0 27.5 13.5t13 28v350q0 14-13 27.75T637-442.5H242.5ZM620-500v-318H143v318h477Zm-477 0v-318 318Z"/></svg> \ No newline at end of file diff --git a/apps/multiplatform/common/src/commonMain/resources/MR/images/ic_schedule.svg b/apps/multiplatform/common/src/commonMain/resources/MR/images/ic_schedule.svg new file mode 100644 index 0000000000..4bd8e90cb6 --- /dev/null +++ b/apps/multiplatform/common/src/commonMain/resources/MR/images/ic_schedule.svg @@ -0,0 +1 @@ +<svg xmlns="http://www.w3.org/2000/svg" height="24" viewBox="0 -960 960 960" width="24"><path d="M512-491.5V-663q0-11.925-8.288-20.213-8.287-8.287-20.212-8.287-12.5 0-20.75 8.287-8.25 8.288-8.25 20.213v183q0 5.832 2 10.675 2 4.842 5.543 9.325l143.572 148.538Q614-301.5 627-302q13-.5 22-9.5 8.5-8.5 8.5-21t-8.458-21.458L512-491.5ZM480.064-85q-80.971 0-153.129-31.263-72.159-31.263-125.797-85Q147.5-255 116.25-327.023 85-399.046 85-479.936q0-80.971 31.263-153.129 31.263-72.159 85-125.797Q255-812.5 327.023-843.75 399.046-875 479.936-875q80.971 0 153.129 31.263 72.159 31.263 125.797 85Q812.5-705 843.75-632.977 875-560.954 875-480.064q0 80.971-31.263 153.129-31.263 72.159-85 125.797Q705-147.5 632.977-116.25 560.954-85 480.064-85ZM480-480Zm-.25 337.5q138.75 0 238.25-99.25t99.5-238q0-138.75-99.48-238.25-99.481-99.5-238.02-99.5-139 0-238.25 99.48Q142.5-618.539 142.5-480q0 139 99.25 238.25t238 99.25Z"/></svg> \ No newline at end of file diff --git a/apps/multiplatform/common/src/commonMain/resources/MR/images/ic_schedule_filled.svg b/apps/multiplatform/common/src/commonMain/resources/MR/images/ic_schedule_filled.svg new file mode 100644 index 0000000000..368e2fcc1f --- /dev/null +++ b/apps/multiplatform/common/src/commonMain/resources/MR/images/ic_schedule_filled.svg @@ -0,0 +1 @@ +<svg xmlns="http://www.w3.org/2000/svg" height="24" viewBox="0 -960 960 960" width="24"><path d="M512-491.5V-663q0-11.925-8.288-20.213-8.287-8.287-20.212-8.287-12.5 0-20.75 8.287-8.25 8.288-8.25 20.213v183q0 5.832 2 10.675 2 4.842 5.543 9.325l143.572 148.538Q614-301.5 627-302q13-.5 22-9.5 8.5-8.5 8.5-21t-8.458-21.458L512-491.5ZM480.064-85q-80.971 0-153.129-31.263-72.159-31.263-125.797-85Q147.5-255 116.25-327.023 85-399.046 85-479.936q0-80.971 31.263-153.129 31.263-72.159 85-125.797Q255-812.5 327.023-843.75 399.046-875 479.936-875q80.971 0 153.129 31.263 72.159 31.263 125.797 85Q812.5-705 843.75-632.977 875-560.954 875-480.064q0 80.971-31.263 153.129-31.263 72.159-85 125.797Q705-147.5 632.977-116.25 560.954-85 480.064-85Z"/></svg> \ No newline at end of file diff --git a/apps/multiplatform/common/src/commonMain/resources/MR/it/strings.xml b/apps/multiplatform/common/src/commonMain/resources/MR/it/strings.xml index 79c1897153..15029be968 100644 --- a/apps/multiplatform/common/src/commonMain/resources/MR/it/strings.xml +++ b/apps/multiplatform/common/src/commonMain/resources/MR/it/strings.xml @@ -41,7 +41,7 @@ <string name="description_via_contact_address_link_incognito">incognito via link indirizzo del contatto</string> <string name="description_via_one_time_link">via link una tantum</string> <string name="description_via_one_time_link_incognito">incognito via link una tantum</string> - <string name="simplex_link_contact">Indirizzo del contatto SimpleX</string> + <string name="simplex_link_contact">Indirizzo di contatto SimpleX</string> <string name="simplex_link_invitation">Invito SimpleX una tantum</string> <string name="simplex_link_group">Link gruppo SimpleX</string> <string name="simplex_link_mode_full">Link completo</string> @@ -237,12 +237,12 @@ <string name="accept">Accetta</string> <string name="v4_2_group_links_desc">Gli amministratori possono creare i link per entrare nei gruppi.</string> <string name="allow_disappearing_messages_only_if">Consenti i messaggi a tempo solo se il tuo contatto li consente.</string> - <string name="allow_to_delete_messages">Permetti di eliminare irreversibilmente i messaggi inviati.</string> + <string name="allow_to_delete_messages">Permetti di eliminare irreversibilmente i messaggi inviati. (24 ore)</string> <string name="allow_your_contacts_to_send_disappearing_messages">Permetti ai tuoi contatti di inviare messaggi a tempo.</string> <string name="network_enable_socks_info">Accedere ai server via proxy SOCKS sulla porta %d\? Il proxy deve essere avviato prima di attivare questa opzione.</string> <string name="v4_3_improved_server_configuration_desc">Aggiungi server scansionando codici QR.</string> <string name="all_group_members_will_remain_connected">Tutti i membri del gruppo resteranno connessi.</string> - <string name="allow_irreversible_message_deletion_only_if">Consenti l\'eliminazione irreversibile dei messaggi solo se il contatto la consente a te.</string> + <string name="allow_irreversible_message_deletion_only_if">Consenti l\'eliminazione irreversibile dei messaggi solo se il contatto la consente a te. (24 ore)</string> <string name="above_then_preposition_continuation">sopra, quindi:</string> <string name="accept_contact_button">Accetta</string> <string name="accept_connection_request__question">Accettare la richiesta di connessione\?</string> @@ -257,7 +257,7 @@ <string name="color_primary">Principale</string> <string name="accept_feature">Accetta</string> <string name="allow_voice_messages_only_if">Consenti i messaggi vocali solo se il tuo contatto li consente.</string> - <string name="allow_your_contacts_irreversibly_delete">Permetti ai tuoi contatti di eliminare irreversibilmente i messaggi inviati.</string> + <string name="allow_your_contacts_irreversibly_delete">Permetti ai tuoi contatti di eliminare irreversibilmente i messaggi inviati. (24 ore)</string> <string name="allow_direct_messages">Permetti l\'invio di messaggi diretti ai membri.</string> <string name="allow_to_send_disappearing">Permetti l\'invio di messaggi a tempo.</string> <string name="allow_to_send_voice">Permetti l\'invio di messaggi vocali.</string> @@ -292,8 +292,6 @@ <string name="delete_group_menu_action">Elimina</string> <string name="direct_messages_are_prohibited_in_chat">I messaggi diretti tra i membri sono vietati in questo gruppo.</string> <string name="display_name">Inserisci il tuo nome:</string> - <string name="add_new_contact_to_create_one_time_QR_code"><![CDATA[<b>Aggiungi un contatto</b>: per creare il tuo codice QR una tantum per il tuo contatto.]]></string> - <string name="scan_QR_code_to_connect_to_contact_who_shows_QR_code"><![CDATA[<b>Scansiona codice QR</b>: per connetterti al contatto che ti mostra il codice QR.]]></string> <string name="choose_file">File</string> <string name="clear_chat_button">Svuota chat</string> <string name="clear_chat_question">Svuotare la chat\?</string> @@ -319,7 +317,6 @@ <string name="clear_verification">Annulla la verifica</string> <string name="connect_button">Connetti</string> <string name="connect_via_link">Connetti via link</string> - <string name="create_one_time_link">Crea link di invito una tantum</string> <string name="database_passphrase_and_export">Password del database ed esportazione</string> <string name="smp_servers_enter_manually">Inserisci il server manualmente</string> <string name="how_to_use_simplex_chat">Come si usa</string> @@ -461,7 +458,7 @@ <string name="group_display_name_field">Inserisci il nome del gruppo:</string> <string name="group_profile_is_stored_on_members_devices">Il profilo del gruppo è memorizzato sui dispositivi dei membri, non sui server.</string> <string name="chat_preferences_always">sempre</string> - <string name="both_you_and_your_contacts_can_delete">Sia tu che il tuo contatto potete eliminare irreversibilmente i messaggi inviati.</string> + <string name="both_you_and_your_contacts_can_delete">Sia tu che il tuo contatto potete eliminare irreversibilmente i messaggi inviati. (24 ore)</string> <string name="both_you_and_your_contact_can_send_disappearing">Sia tu che il tuo contatto potete inviare messaggi a tempo.</string> <string name="both_you_and_your_contact_can_send_voice">Sia tu che il tuo contatto potete inviare messaggi vocali.</string> <string name="chat_preferences">Preferenze della chat</string> @@ -498,7 +495,7 @@ <string name="ttl_week">%d settimana</string> <string name="ttl_weeks">%d settimane</string> <string name="v4_2_group_links">Link del gruppo</string> - <string name="group_members_can_delete">I membri del gruppo possono eliminare irreversibilmente i messaggi inviati.</string> + <string name="group_members_can_delete">I membri del gruppo possono eliminare irreversibilmente i messaggi inviati. (24 ore)</string> <string name="group_members_can_send_dms">I membri del gruppo possono inviare messaggi diretti.</string> <string name="group_members_can_send_disappearing">I membri del gruppo possono inviare messaggi a tempo.</string> <string name="group_members_can_send_voice">I membri del gruppo possono inviare messaggi vocali.</string> @@ -508,7 +505,7 @@ <string name="keychain_allows_to_receive_ntfs">Android Keystore verrà usato per memorizzare in modo sicuro la password dopo il riavvio dell\'app o la modifica della password; consentirà di ricevere le notifiche.</string> <string name="impossible_to_recover_passphrase"><![CDATA[<b>Nota bene</b>: NON potrai recuperare o cambiare la password se la perdi.]]></string> <string name="change_database_passphrase_question">Cambiare password del database\?</string> - <string name="confirm_new_passphrase">Conferma password nuova…</string> + <string name="confirm_new_passphrase">Conferma nuova password…</string> <string name="current_passphrase">Password attuale…</string> <string name="database_encrypted">Database crittografato!</string> <string name="database_passphrase_will_be_updated">La password di crittografia del database verrà aggiornata.</string> @@ -623,7 +620,7 @@ <string name="save_servers_button">Salva</string> <string name="saved_ICE_servers_will_be_removed">I server WebRTC ICE salvati verranno rimossi.</string> <string name="share_link">Condividi link</string> - <string name="star_on_github">Stella su GitHub</string> + <string name="star_on_github">Dai una stella su GitHub</string> <string name="update_onion_hosts_settings_question">Aggiornare l\'impostazione degli host .onion\?</string> <string name="network_disable_socks">Usare una connessione internet diretta\?</string> <string name="network_use_onion_hosts">Usa gli host .onion</string> @@ -665,7 +662,7 @@ <string name="many_people_asked_how_can_it_deliver"><![CDATA[Molte persone hanno chiesto: <i>se SimpleX non ha identificatori utente, come può recapitare i messaggi\?</i>]]></string> <string name="only_client_devices_store_contacts_groups_e2e_encrypted_messages"><![CDATA[Solo i dispositivi client memorizzano i profili utente, i contatti, i gruppi e i messaggi inviati con <b>crittografia end-to-end a 2 livelli</b>.]]></string> <string name="opensource_protocol_and_code_anybody_can_run_servers">Protocollo e codice open source: chiunque può gestire i server.</string> - <string name="paste_the_link_you_received">Incolla il link ricevuto</string> + <string name="paste_the_link_you_received">Incolla il link che hai ricevuto</string> <string name="people_can_connect_only_via_links_you_share">Le persone possono connettersi a te solo tramite i link che condividi.</string> <string name="onboarding_notifications_mode_periodic">Periodico</string> <string name="privacy_redefined">Privacy ridefinita</string> @@ -681,7 +678,7 @@ <string name="video_call_no_encryption">videochiamata (non crittografata e2e)</string> <string name="onboarding_notifications_mode_off">Quando l\'app è in esecuzione</string> <string name="contact_wants_to_connect_via_call">%1$s vuole connettersi con te via</string> - <string name="you_control_servers_to_receive_your_contacts_to_send"><![CDATA[Puoi controllare attraverso quale/i server <b>ricevere</b> i messaggi, i tuoi contatti – i server che usi per inviare loro i messaggi.]]></string> + <string name="you_control_servers_to_receive_your_contacts_to_send"><![CDATA[Tu decidi attraverso quale/i server <b>ricevere</b> i messaggi, i tuoi contatti quali server usi per inviare loro i messaggi.]]></string> <string name="alert_text_skipped_messages_it_can_happen_when">Può accadere quando: \n1. I messaggi sono scaduti sul client mittente dopo 2 giorni o sul server dopo 30 giorni. \n2. La decifrazione del messaggio è fallita, perché tu o il tuo contatto avete usato un backup del database vecchio. @@ -775,7 +772,7 @@ <string name="group_invitation_tap_to_join">Tocca per entrare</string> <string name="group_invitation_tap_to_join_incognito">Toccare per entrare in incognito</string> <string name="alert_message_no_group">Questo gruppo non esiste più.</string> - <string name="rcv_group_event_updated_group_profile">profilo del gruppo aggiornato</string> + <string name="rcv_group_event_updated_group_profile">ha aggiornato il profilo del gruppo</string> <string name="you_are_invited_to_group">Sei stato/a invitato/a al gruppo</string> <string name="snd_conn_event_switch_queue_phase_completed">hai cambiato indirizzo</string> <string name="snd_conn_event_switch_queue_phase_completed_for_member">hai cambiato l\'indirizzo per %s</string> @@ -842,9 +839,9 @@ <string name="chat_preferences_off">off</string> <string name="feature_off">off</string> <string name="chat_preferences_on">on</string> - <string name="only_you_can_delete_messages">Solo tu puoi eliminare irreversibilmente i messaggi (il tuo contatto può contrassegnarli per l\'eliminazione).</string> + <string name="only_you_can_delete_messages">Solo tu puoi eliminare irreversibilmente i messaggi (il tuo contatto può contrassegnarli per l\'eliminazione). (24 ore)</string> <string name="only_you_can_send_disappearing">Solo tu puoi inviare messaggi a tempo.</string> - <string name="only_your_contact_can_delete">Solo il tuo contatto può eliminare irreversibilmente i messaggi (tu puoi contrassegnarli per l\'eliminazione).</string> + <string name="only_your_contact_can_delete">Solo il tuo contatto può eliminare irreversibilmente i messaggi (tu puoi contrassegnarli per l\'eliminazione). (24 ore)</string> <string name="only_your_contact_can_send_disappearing">Solo il tuo contatto può inviare messaggi a tempo.</string> <string name="prohibit_sending_disappearing_messages">Proibisci l\'invio di messaggi a tempo.</string> <string name="prohibit_sending_voice_messages">Proibisci l\'invio di messaggi vocali.</string> @@ -972,8 +969,6 @@ <string name="tap_to_activate_profile">Tocca per attivare il profilo.</string> <string name="user_unhide">Svela</string> <string name="make_profile_private">Rendi privato il profilo!</string> - <string name="should_be_at_least_one_profile">Deve esserci almeno un profilo utente.</string> - <string name="should_be_at_least_one_visible_profile">Deve esserci almeno un profilo utente visibile.</string> <string name="you_can_hide_or_mute_user_profile">Puoi nascondere o silenziare un profilo utente - tienilo premuto per il menu.</string> <string name="dont_show_again">Non mostrare più</string> <string name="muted_when_inactive">Silenzioso quando inattivo!</string> @@ -993,7 +988,6 @@ <string name="v4_6_group_moderation_descr">Ora gli amministratori possono: \n- eliminare i messaggi dei membri. \n- disattivare i membri (ruolo \"osservatore\")</string> - <string name="cant_delete_user_profile">Impossibile eliminare il profilo utente!</string> <string name="hide_profile">Nascondi il profilo</string> <string name="confirm_password">Conferma password</string> <string name="error_updating_user_privacy">Errore nell\'aggiornamento della privacy dell\'utente</string> @@ -1368,9 +1362,9 @@ <string name="system_restricted_background_desc">SimpleX non può funzionare in secondo piano. Riceverai le notifiche solo quando l\'app è aperta.</string> <string name="system_restricted_background_warn"><![CDATA[Per attivare le notifiche, scegli <b>Utilizzo batteria dell\'app</b> / <b>Senza restrizioni</b> nelle impostazioni.]]></string> <string name="system_restricted_background_in_call_warn"><![CDATA[Per effettuare chiamate in secondo piano, scegli <b>Utilizzo batteria dell\'app</b> / <b>Senza restrizioni</b> nelle impostazioni.]]></string> - <string name="rcv_group_event_2_members_connected">%s e %s sono connessi/e</string> - <string name="rcv_group_event_n_members_connected">%s, %s e altri %d membri sono connessi</string> - <string name="rcv_group_event_3_members_connected">%s, %s e %s sono connessi/e</string> + <string name="rcv_group_event_2_members_connected">%s e %s si sono connessi/e</string> + <string name="rcv_group_event_n_members_connected">%s, %s e altri %d membri si sono connessi</string> + <string name="rcv_group_event_3_members_connected">%s, %s e %s si sono connessi/e</string> <string name="privacy_message_draft">Bozza</string> <string name="privacy_show_last_messages">Mostra gli ultimi messaggi</string> <string name="database_will_be_encrypted_and_passphrase_stored_in_settings">Il database verrà crittografato e la password conservata nelle impostazioni.</string> @@ -1380,7 +1374,7 @@ <string name="remove_passphrase_from_settings">Rimuovere la password dalle impostazioni\?</string> <string name="use_random_passphrase">Usa password casuale</string> <string name="save_passphrase_in_settings">Salva password nelle impostazioni</string> - <string name="setup_database_passphrase">Configura password del database</string> + <string name="setup_database_passphrase">Configura la password del database</string> <string name="set_database_passphrase">Imposta password del database</string> <string name="open_database_folder">Apri cartella del database</string> <string name="passphrase_will_be_saved_in_settings">La password verrà conservata nelle impostazioni come testo normale dopo averla cambiata o il riavvio dell\'app.</string> @@ -1407,14 +1401,14 @@ <string name="expand_verb">Espandi</string> <string name="connect_plan_repeat_connection_request">Ripetere la richiesta di connessione?</string> <string name="rcv_direct_event_contact_deleted">contatto eliminato</string> - <string name="connect_plan_you_are_already_connecting_to_vName">Ti stai già connettendo a %1$s.</string> + <string name="connect_plan_you_are_already_connecting_to_vName"><![CDATA[Ti stai già connettendo a <b>%1$s</b>.]]></string> <string name="error_alert_title">Errore</string> <string name="connect_plan_you_are_already_joining_the_group_via_this_link">Stai già entrando nel gruppo tramite questo link.</string> <string name="create_group_button">Crea gruppo</string> <string name="create_another_profile_button">Crea profilo</string> <string name="group_members_2">%s e %s</string> <string name="connect_plan_join_your_group">Entrare nel tuo gruppo?</string> - <string name="connect_plan_you_are_already_joining_the_group_vName">Stai già entrando nel gruppo %1$s.</string> + <string name="connect_plan_you_are_already_joining_the_group_vName"><![CDATA[Stai già entrando nel gruppo <b>%1$s</b>.]]></string> <string name="connect_plan_this_is_your_own_one_time_link">Questo è il tuo link una tantum!</string> <string name="marked_deleted_items_description">%d messaggi contrassegnati eliminati</string> <string name="connect_plan_group_already_exists">Il gruppo esiste già!</string> @@ -1425,11 +1419,11 @@ <string name="connect_plan_connect_via_link">Connettere via link?</string> <string name="connect_plan_already_joining_the_group">Stai già entrando nel gruppo!</string> <string name="group_members_n">%s, %s e %d membri</string> - <string name="moderated_items_description">%d messaggi moderati da %s</string> + <string name="moderated_items_description">%1$d messaggi moderati da %2$s</string> <string name="unblock_member_button">Sblocca membro</string> <string name="connect_plan_connect_to_yourself">Connettersi a te stesso?</string> <string name="contact_tap_to_connect">Tocca per connettere</string> - <string name="connect_plan_you_are_already_in_group_vName">Sei già nel gruppo %1$s.</string> + <string name="connect_plan_you_are_already_in_group_vName"><![CDATA[Sei già nel gruppo <b>%1$s</b>.]]></string> <string name="connect_plan_this_is_your_own_simplex_address">Questo è il tuo indirizzo SimpleX!</string> <string name="correct_name_to">Correggere il nome a %s?</string> <string name="delete_messages__question">Eliminare %d messaggi?</string> @@ -1450,7 +1444,7 @@ <string name="block_member_question">Bloccare il membro?</string> <string name="rcv_group_events_count">%d eventi del gruppo</string> <string name="invalid_name">Nome non valido!</string> - <string name="connect_plan_this_is_your_link_for_group_vName">Questo è il tuo link per il gruppo %1$s!</string> + <string name="connect_plan_this_is_your_link_for_group_vName"><![CDATA[Questo è il tuo link per il gruppo <b>%1$s</b>!]]></string> <string name="unblock_member_confirmation">Sblocca</string> <string name="non_content_uri_alert_title">Percorso file non valido</string> <string name="connect_plan_you_have_already_requested_connection_via_this_address">Hai già richiesto la connessione tramite questo indirizzo!</string> @@ -1469,7 +1463,7 @@ <string name="unlink_desktop_question">Scollegare il desktop?</string> <string name="linked_desktop_options">Opzioni del desktop collegato</string> <string name="linked_desktops">Desktop collegati</string> - <string name="discover_on_network">Trova nella rete</string> + <string name="discover_on_network">Individua via rete locale</string> <string name="this_device">Questo dispositivo</string> <string name="linked_mobiles">Cellulari collegati</string> <string name="desktop_device">Desktop</string> @@ -1517,4 +1511,125 @@ \n- e molto altro!</string> <string name="waiting_for_mobile_to_connect">In attesa che il cellulare si connette:</string> <string name="group_member_role_author">autore</string> + <string name="multicast_connect_automatically">Connetti automaticamente</string> + <string name="waiting_for_desktop">In attesa del desktop…</string> + <string name="found_desktop">Desktop trovato</string> + <string name="not_compatible">Non compatibile!</string> + <string name="multicast_discoverable_via_local_network">individuabile via rete locale</string> + <string name="refresh_qr_code">Ricarica</string> + <string name="create_chat_profile">Crea profilo di chat</string> + <string name="no_connected_mobile">Nessun cellulare connesso</string> + <string name="disconnect_remote_hosts">Disconnetti cellulari</string> + <string name="random_port">Casuale</string> + <string name="open_port_in_firewall_desc">Per consentire a un\'app mobile di connettersi al desktop, apri questa porta nel tuo firewall, se è attivo</string> + <string name="app_was_crashed">Vedi crash</string> + <string name="open_port_in_firewall_title">Apri porta nel firewall</string> + <string name="error_showing_content">errore di visualizzazione del contenuto</string> + <string name="error_showing_message">errore di visualizzazione del messaggio</string> + <string name="you_can_make_address_visible_via_settings">Puoi renderlo visibile ai tuoi contatti SimpleX nelle impostazioni.</string> + <string name="recent_history_is_not_sent_to_new_members">La cronologia non viene inviata ai nuovi membri.</string> + <string name="retry_verb">Riprova</string> + <string name="camera_not_available">Fotocamera non disponibile</string> + <string name="enable_sending_recent_history">Invia fino a 100 ultimi messaggi ai nuovi membri.</string> + <string name="add_contact_button_to_create_link_or_connect_via_link"><![CDATA[<b>Aggiungi contatto</b>: per creare un nuovo link di invito o connetterti tramite un link che hai ricevuto.]]></string> + <string name="disable_sending_recent_history">Non inviare la cronologia ai nuovi membri.</string> + <string name="or_show_this_qr_code">O mostra questo codice</string> + <string name="recent_history_is_sent_to_new_members">Vengono inviati ai nuovi membri fino a 100 ultimi messaggi.</string> + <string name="code_you_scanned_is_not_simplex_link_qr_code">Il codice che hai scansionato non è un codice QR di link SimpleX.</string> + <string name="the_text_you_pasted_is_not_a_link">Il testo che hai incollato non è un link SimpleX.</string> + <string name="enable_camera_access">Attiva l\'accesso alla fotocamera</string> + <string name="you_can_view_invitation_link_again">Puoi vedere di nuovo il link di invito nei dettagli di connessione.</string> + <string name="keep_unused_invitation_question">Tenere l\'invito inutilizzato?</string> + <string name="share_this_1_time_link">Condividi questo link di invito una tantum</string> + <string name="create_group_button_to_create_new_group"><![CDATA[<b>Crea gruppo</b>: per creare un nuovo gruppo.]]></string> + <string name="recent_history">Cronologia visibile</string> + <string name="la_app_passcode">Password dell\'app</string> + <string name="new_chat">Nuova chat</string> + <string name="loading_chats">Caricamento delle chat…</string> + <string name="creating_link">Creazione link…</string> + <string name="or_scan_qr_code">O scansiona il codice QR</string> + <string name="invalid_qr_code">Codice QR non valido</string> + <string name="add_contact_tab">Aggiungi contatto</string> + <string name="tap_to_scan">Tocca per scansionare</string> + <string name="keep_invitation_link">Tieni</string> + <string name="tap_to_paste_link">Tocca per incollare il link</string> + <string name="search_or_paste_simplex_link">Cerca o incolla un link SimpleX</string> + <string name="chat_is_stopped_you_should_transfer_database">La chat è ferma. Se hai già usato questo database su un altro dispositivo, dovresti trasferirlo prima di avviare la chat.</string> + <string name="start_chat_question">Avviare la chat?</string> + <string name="agent_critical_error_title">Errore critico</string> + <string name="agent_internal_error_title">Errore interno</string> + <string name="agent_critical_error_desc">Si prega di segnalarlo agli sviluppatori: +\n%s +\n +\nSi consiglia di riavviare l\'app.</string> + <string name="agent_internal_error_desc">Si prega di segnalarlo agli sviluppatori: +\n%s</string> + <string name="restart_chat_button">Riavvia la chat</string> + <string name="show_internal_errors">Mostra errori interni</string> + <string name="remote_host_disconnected_from"><![CDATA[Disconnesso dal telefono <b>%s</b> per il motivo: %s]]></string> + <string name="remote_ctrl_disconnected_with_reason">Disconnesso per il motivo: %s</string> + <string name="remote_host_was_disconnected_title">Connessione interrotta</string> + <string name="remote_ctrl_was_disconnected_title">Connessione interrotta</string> + <string name="remote_host_error_missing"><![CDATA[Telefono <b>%s</b> non trovato]]></string> + <string name="remote_ctrl_error_busy">Il desktop è occupato</string> + <string name="remote_ctrl_error_bad_version">Il desktop ha una versione non supportata. Assicurati di usare la stessa versione su entrambi i dispositivi</string> + <string name="failed_to_create_user_invalid_title">Nome da mostrare non valido!</string> + <string name="failed_to_create_user_invalid_desc">Questo nome da mostrare non è valido. Scegline un altro.</string> + <string name="remote_host_error_bad_state"><![CDATA[La connessione al telefono <b>%s</b> è in cattivo stato]]></string> + <string name="remote_host_error_bad_version"><![CDATA[Il telefono <b>%s</b> ha una versione non supportata. Assicurati di usare la stessa versione su entrambi i dispositivi]]></string> + <string name="remote_host_error_busy"><![CDATA[Il telefono <b>%s</b> è occupato]]></string> + <string name="remote_host_error_inactive"><![CDATA[Il telefono <b>%s</b> è inattivo]]></string> + <string name="remote_host_error_disconnected"><![CDATA[Il telefono <b>%s</b> è stato disconnesso]]></string> + <string name="remote_host_error_timeout"><![CDATA[Tempo scaduto durante la connessione al telefono <b>%s</b>]]></string> + <string name="remote_ctrl_error_bad_state">La connessione al desktop è in cattivo stato</string> + <string name="remote_ctrl_error_bad_invitation">Il desktop ha un codice di invito sbagliato</string> + <string name="remote_ctrl_error_inactive">Il desktop è inattivo</string> + <string name="remote_ctrl_error_disconnected">Il desktop è stato disconnesso</string> + <string name="remote_ctrl_error_timeout">Tempo scaduto durante la connessione al desktop</string> + <string name="past_member_vName">Membro passato %1$s</string> + <string name="possible_slow_function_desc">L\'esecuzione della funzione impiega troppo tempo: %1$d secondi: %2$s</string> + <string name="possible_slow_function_title">Funzione lenta</string> + <string name="show_slow_api_calls">Mostra chiamate API lente</string> + <string name="group_member_status_unknown_short">sconosciuto</string> + <string name="possible_deadlock_desc">L\'esecuzione del codice impiega troppo tempo: %1$d secondi. Probabilmente l\'app è congelata: %2$s</string> + <string name="group_member_status_unknown">stato sconosciuto</string> + <string name="possible_deadlock_title">Stallo</string> + <string name="developer_options_section">Opzioni sviluppatore</string> + <string name="v5_5_private_notes">Note private</string> + <string name="v5_5_new_interface_languages">Interfaccia in ungherese e turco</string> + <string name="v5_5_join_group_conversation_descr">Cronologia recente e bot della directory migliorato.</string> + <string name="info_row_created_at">Creato il</string> + <string name="clear_note_folder_warning">Tutti i messaggi verranno eliminati, non è reversibile!</string> + <string name="share_text_created_at">Creato il: %s</string> + <string name="error_creating_message">Errore di creazione del messaggio</string> + <string name="error_deleting_note_folder">Errore di eliminazione delle note private</string> + <string name="v5_5_message_delivery">Consegna dei messaggi migliorata</string> + <string name="v5_5_join_group_conversation">Entra in conversazioni di gruppo</string> + <string name="profile_update_event_member_name_changed">membro %1$s cambiato in %2$s</string> + <string name="v5_5_simpler_connect_ui">Incolla un link per connettere!</string> + <string name="profile_update_event_removed_address">indirizzo di contatto rimosso</string> + <string name="profile_update_event_contact_name_changed">contatto %1$s cambiato in %2$s</string> + <string name="note_folder_local_display_name">Note private</string> + <string name="clear_note_folder_question">Svuotare le note private?</string> + <string name="profile_update_event_removed_picture">immagine del profilo rimossa</string> + <string name="v5_5_private_notes_descr">Con file e multimediali criptati.</string> + <string name="v5_5_simpler_connect_ui_descr">La barra di ricerca accetta i link di invito.</string> + <string name="profile_update_event_set_new_picture">impostata nuova immagine del profilo</string> + <string name="profile_update_event_set_new_address">impostato nuovo indirizzo di contatto</string> + <string name="profile_update_event_updated_profile">profilo aggiornato</string> + <string name="saved_message_title">Messaggio salvato</string> + <string name="v5_5_message_delivery_descr">Con consumo di batteria ridotto.</string> + <string name="blocked_by_admin_items_description">%d messaggi bloccati dall\'amministratore</string> + <string name="rcv_group_event_member_blocked">ha bloccato %s</string> + <string name="rcv_group_event_member_unblocked">ha sbloccato %s</string> + <string name="snd_group_event_member_unblocked">hai sbloccato %s</string> + <string name="unblock_for_all">Sblocca per tutti</string> + <string name="unblock_for_all_question">Sbloccare il membro per tutti?</string> + <string name="block_for_all">Blocca per tutti</string> + <string name="member_info_member_blocked">bloccato</string> + <string name="blocked_by_admin_item_description">bloccato dall\'amministratore</string> + <string name="member_blocked_by_admin">Bloccato dall\'amministratore</string> + <string name="block_for_all_question">Bloccare il membro per tutti?</string> + <string name="error_blocking_member_for_all">Errore nel blocco del membro per tutti</string> + <string name="snd_group_event_member_blocked">hai bloccato %s</string> </resources> \ No newline at end of file diff --git a/apps/multiplatform/common/src/commonMain/resources/MR/iw/strings.xml b/apps/multiplatform/common/src/commonMain/resources/MR/iw/strings.xml index 58bb6b0a0a..1d5a7b690d 100644 --- a/apps/multiplatform/common/src/commonMain/resources/MR/iw/strings.xml +++ b/apps/multiplatform/common/src/commonMain/resources/MR/iw/strings.xml @@ -93,7 +93,6 @@ <string name="v4_2_auto_accept_contact_requests">אשר אוטומטית בקשות ליצירת קשר.</string> <string name="authentication_cancelled">אימות בוטל</string> <string name="auth_unavailable">אימות לא זמין</string> - <string name="add_new_contact_to_create_one_time_QR_code"><![CDATA[<b>הוסיפו איש קשר חדש</b>: ליצירת קוד QR חד־פעמי עבור איש הקשר שלכם.]]></string> <string name="onboarding_notifications_mode_off_desc"><![CDATA[<b>הטוב ביותר לסוללה</b>. התראות יוצגו רק כאשר האפליקציה מופעלת (ללא שירות רקע).]]></string> <string name="onboarding_notifications_mode_periodic_desc"><![CDATA[<b>טוב לסוללה</b>. שירות הרקע ייבדוק הודעות כל 10 דקות. שיחות או הודעות דחופות עלולות להתפספס.]]></string> <string name="both_you_and_your_contacts_can_delete">גם אתם וגם איש הקשר יכולים למחוק באופן בלתי הפיך הודעות שנשלחו.</string> @@ -103,7 +102,6 @@ <string name="cancel_verb">ביטול</string> <string name="icon_descr_cancel_live_message">בטל הודעה חיה</string> <string name="use_camera_button">מצלמה</string> - <string name="scan_QR_code_to_connect_to_contact_who_shows_QR_code"><![CDATA[<b>סירקו קוד QR</b>: כדי להתחבר לאיש קשר המציג לכם קוד QR.]]></string> <string name="icon_descr_cancel_link_preview">בטל תצוגה מקדימה של קישורים</string> <string name="callstatus_error">שגיאת שיחה</string> <string name="callstatus_in_progress">שיחה מתמשכת</string> @@ -114,7 +112,6 @@ <string name="icon_descr_call_progress">שיחה מתמשכת</string> <string name="settings_section_title_calls">שיחות</string> <string name="cannot_access_keychain">לא ניתן לגשת ל־Keystore כדי לאחסן את סיסמת מסד הנתונים</string> - <string name="cant_delete_user_profile">לא ניתן למחוק פרופיל משתמש!</string> <string name="feature_cancelled_item">בוטל %s</string> <string name="v4_5_transport_isolation_descr">לפי פרופיל צ׳אט (ברירת מחדל) או לפי חיבור (בביטא).</string> <string name="callstatus_calling">מתקשר…</string> @@ -219,7 +216,6 @@ <string name="copied">הועתק ללוח</string> <string name="share_one_time_link">צור קישור הזמנה חד־פעמי</string> <string name="create_group">צור קבוצה סודית</string> - <string name="create_one_time_link">צור קישור הזמנה חד־פעמי</string> <string name="contribute">תרומה</string> <string name="core_version">גרסת ליבה: v%s</string> <string name="create_address">צור כתובת</string> @@ -1058,8 +1054,6 @@ <string name="messages_section_description">הגדרה זו חלה על הודעות בפרופיל הצ׳אט הנוכחי שלך</string> <string name="database_backup_can_be_restored">הניסיון לשנות את סיסמת מסד הנתונים לא הושלם.</string> <string name="color_title">כותרת</string> - <string name="should_be_at_least_one_profile">נדרש לפחות פרופיל משתמש אחד.</string> - <string name="should_be_at_least_one_visible_profile">נדרש לפחות פרופיל משתמש אחד גלוי.</string> <string name="group_is_decentralized">הקבוצה מבוזרת לחלוטין - היא גלויה רק לחברי הקבוצה.</string> <string name="to_protect_privacy_simplex_has_ids_for_queues">כדי לשמור על הפרטיות, במקום מזהי משתמש הקיימים בכל הפלטפורמות האחרות, ל־SimpleX יש מזהים לתורי הודעות, נפרדים עבור כל אחד מאנשי הקשר שלך.</string> <string name="using_simplex_chat_servers">משתמש בשרתי SimpleX Chatז</string> diff --git a/apps/multiplatform/common/src/commonMain/resources/MR/ja/strings.xml b/apps/multiplatform/common/src/commonMain/resources/MR/ja/strings.xml index bebf716e0d..2951b13155 100644 --- a/apps/multiplatform/common/src/commonMain/resources/MR/ja/strings.xml +++ b/apps/multiplatform/common/src/commonMain/resources/MR/ja/strings.xml @@ -49,7 +49,7 @@ <string name="impossible_to_recover_passphrase"><![CDATA[<b>※注意※</b>:喪失したら、パスフレーズの回復・変更ができません。]]></string> <string name="all_group_members_will_remain_connected">グループ全員の接続が継続します。</string> <string name="allow_your_contacts_to_send_disappearing_messages">送信相手が消えるメッセージを送るのを許可する。</string> - <string name="allow_your_contacts_irreversibly_delete">送信相手が永久メッセージ削除するのを許可する。</string> + <string name="allow_your_contacts_irreversibly_delete">送信相手が永久メッセージ削除するのを許可する。(24時間)</string> <string name="allow_voice_messages_only_if">送信相手も音声メッセージを許可する時のみに許可する。</string> <string name="both_you_and_your_contact_can_send_disappearing">あなたと連絡相手が消えるメッセージを送信できます。</string> <string name="v4_2_auto_accept_contact_requests">連絡先を自動的に承諾</string> @@ -57,8 +57,8 @@ <string name="notifications_mode_service">常にオン</string> <string name="clear_chat_warning">全てのメッセージが削除されます(※注意:元に戻せません!※)。削除されるのは片方あなたのメッセージのみ</string> <string name="allow_disappearing_messages_only_if">送信相手も消えるメッセージ機能を許可する時のみに許可する。</string> - <string name="allow_irreversible_message_deletion_only_if">送信相手も永久メッセージ削除を許可する時のみに許可する。</string> - <string name="allow_to_delete_messages">送信済みメッセージの永久削除を許可</string> + <string name="allow_irreversible_message_deletion_only_if">送信相手も永久メッセージ削除を許可する時のみに許可する。(24時間)</string> + <string name="allow_to_delete_messages">送信済みメッセージの永久削除を許可(24時間)</string> <string name="allow_to_send_disappearing">消えるメッセージの送信を許可</string> <string name="allow_direct_messages">メンバーへのダイレクトメッセージを許可</string> <string name="allow_to_send_voice">音声メッセージの送信を許可</string> @@ -73,12 +73,10 @@ <string name="auth_unavailable">認証不可能</string> <string name="auto_accept_images">画像を自動的に受信</string> <string name="notifications_mode_service_desc">バックグラウンド機能が常にオンで、メッセージが到着次第に通知が出ます。</string> - <string name="add_new_contact_to_create_one_time_QR_code"><![CDATA[<b>新しい連絡先を追加</b>:使い捨てのQRコードを発行]]></string> <string name="turning_off_service_and_periodic">電池省エネをオンに、バックグラウンド機能と定期的な受信依頼をオフにします。設定メニューにて変更できます。</string> <string name="onboarding_notifications_mode_off_desc"><![CDATA[<b>電池消費が最少</b>:アプリがアクティブ時のみに通知が出ます(バックグラウンドサービス無し)。]]></string> <string name="it_can_disabled_via_settings_notifications_still_shown"><![CDATA[<b>設定メニューにてオフにできます。</b> アプリがアクティブ時に通知が出ます。]]></string> - <string name="both_you_and_your_contacts_can_delete">あなたと連絡相手が送信済みメッセージを永久削除できます。</string> - <string name="scan_QR_code_to_connect_to_contact_who_shows_QR_code"><![CDATA[<b>QRコードを読み込み</b>:連絡相手のQRコードをスキャンすると繋がります。]]></string> + <string name="both_you_and_your_contacts_can_delete">あなたと連絡相手が送信済みメッセージを永久削除できます。(24時間)</string> <string name="chat_archive_section">チャットのアーカイブ</string> <string name="delete_chat_archive_question">チャットのアーカイブを削除しますか?</string> <string name="join_group_incognito_button">シークレットモードで参加</string> @@ -131,7 +129,7 @@ <string name="how_to">使い方</string> <string name="network_use_onion_hosts_required">必須</string> <string name="incoming_video_call">ビデオ通話着信</string> - <string name="paste_the_link_you_received">頂いたリンクを貼り付ける</string> + <string name="paste_the_link_you_received">受け取ったリンクを貼り付ける</string> <string name="icon_descr_hang_up">通話を切る</string> <string name="messages_section_title">メッセージ</string> <string name="rcv_group_event_invited_via_your_group_link">グループリンク経由で招待された</string> @@ -141,9 +139,9 @@ <string name="error_changing_address">アドレス変更にエラー発生</string> <string name="error_creating_link_for_group">グループリンク発行にエラー発生</string> <string name="error_changing_role">役割変更にエラー発生</string> - <string name="error_exporting_chat_database">チャットデータベースのエキスポートにエラー発生</string> - <string name="error_saving_smp_servers">SMPサーバ保存にエラー発生</string> - <string name="error_saving_ICE_servers">ICEサーバ保存にエラー発生</string> + <string name="error_exporting_chat_database">チャットデータベースの書き出しでエラー発生</string> + <string name="error_saving_smp_servers">SMPサーバ保存でエラー発生</string> + <string name="error_saving_ICE_servers">ICEサーバ保存でエラー発生</string> <string name="error_setting_network_config">ネットワーク設定の更新にエラー発生</string> <string name="icon_descr_file">ファイル</string> <string name="simplex_link_mode_full">フルリンク</string> @@ -151,7 +149,7 @@ <string name="group_invitation_expired">グループ招待が期限切れ</string> <string name="icon_descr_group_inactive">非アクティブなグループ</string> <string name="group_members_can_send_voice">グループのメンバーが音声メッセージを送信できます。</string> - <string name="group_members_can_delete">グループのメンバーがメッセージを完全削除することができます。</string> + <string name="group_members_can_delete">送信したメッセージをグループのメンバーが完全削除することができます。(24時間)</string> <string name="group_profile_is_stored_on_members_devices">グループのプロフィールはサーバではなく、メンバーの端末に保存されます。</string> <string name="snd_group_event_group_profile_updated">グループのプロフィールが更新されました。</string> <string name="notification_display_mode_hidden_desc">連絡先とメッセージ内容をプライベートにする。</string> @@ -183,7 +181,7 @@ <string name="chat_preferences">チャット設定</string> <string name="clear_chat_button">消す</string> <string name="icon_descr_close_button">閉じるボタン</string> - <string name="clear_verification">検証を消す</string> + <string name="clear_verification">未検証の状態に戻す</string> <string name="image_saved">画像をギャラリーに保存しました。</string> <string name="choose_file">ファイル</string> <string name="clear_chat_menu_action">消す</string> @@ -212,9 +210,9 @@ <string name="connection_timeout">接続タイムアウト</string> <string name="connection_request_sent">接続リクエストを送信しました!</string> <string name="connection_local_display_name">接続 %1$d</string> - <string name="connect_via_contact_link">連絡先リンク経由で繋がりますか?</string> - <string name="connect_via_group_link">グループリンク経由で繋がりますか?</string> - <string name="connect_via_invitation_link">招待リンク経由で繋がりますか?</string> + <string name="connect_via_contact_link">連絡先アドレスと接続?</string> + <string name="connect_via_group_link">グループに参加?</string> + <string name="connect_via_invitation_link">ワンタイムリンクで接続?</string> <string name="status_contact_has_e2e_encryption">連絡先はエンドツーエンド暗号化があります。</string> <string name="description_via_group_link_incognito">グループリンク経由でシークレットモード</string> <string name="delete_contact_all_messages_deleted_cannot_undo_warning">連絡先と全メッセージが削除されます (※元に戻せません※)!</string> @@ -230,9 +228,9 @@ <string name="only_group_owners_can_change_prefs">グループ設定を変えられるのはグループのオーナーだけです。</string> <string name="only_group_owners_can_enable_voice">音声メッセージを利用可能に設定できるのはグループのオーナーだけです。</string> <string name="create_profile">プロフィールを作成する</string> - <string name="only_you_can_delete_messages">メッセージの完全削除はあなたにしかできません (あなたの連絡先は削除対象とすることができます)。</string> + <string name="only_you_can_delete_messages">メッセージの完全削除はあなたにしかできません (あなたの連絡先は削除対象とすることができます)。(24時間)</string> <string name="create_your_profile">プロフィールを作成する</string> - <string name="only_your_contact_can_delete">メッセージを完全削除できるのはあなたの連絡相手だけです (あなたは削除対象とすることができます)。</string> + <string name="only_your_contact_can_delete">メッセージを完全削除できるのはあなたの連絡相手だけです (あなたは削除対象とすることができます)。(24時間)</string> <string name="open_chat">チャットを開く</string> <string name="only_your_contact_can_send_voice">音声メッセージを送れるのはあなたの連絡相手だけです。</string> <string name="database_encryption_will_be_updated">データベース暗号化のパスフレーズが更新され、キーストア (暗証キー保管庫)に保存されます。</string> @@ -258,11 +256,11 @@ <string name="alert_title_group_invitation_expired">招待が期限切れました!</string> <string name="smp_servers_delete_server">サーバを削除</string> <string name="auth_device_authentication_is_disabled_turning_off">端末認証がオフです。SimpleXロックを解除します。</string> - <string name="direct_messages_are_prohibited_in_chat">このグループではメンバー間のダイレクトメッセージが使用禁止です。</string> - <string name="disappearing_messages_are_prohibited">このグループでは消えるメッセージが使用禁止です。</string> + <string name="direct_messages_are_prohibited_in_chat">このグループではメンバー間のダイレクトメッセージが無効です。</string> + <string name="disappearing_messages_are_prohibited">このグループでは消えるメッセージが無効です。</string> <string name="ttl_min">%d 分</string> <string name="ttl_weeks">%d 週</string> - <string name="network_option_enable_tcp_keep_alive">TCP keep-aliveを有効にする</string> + <string name="network_option_enable_tcp_keep_alive">TCPキープアライブを有効にする</string> <string name="icon_descr_email">メール</string> <string name="allow_accepting_calls_from_lock_screen">設定メニューでロック画面からの通話を有効にできます。</string> <string name="people_can_connect_only_via_links_you_share">あなたと繋がることができるのは、あなたからリンクを頂いた方のみです。</string> @@ -276,12 +274,12 @@ <string name="display_name_connecting">接続待ち…</string> <string name="description_via_contact_address_link_incognito">連絡先リンク経由でシークレットモード</string> <string name="description_via_one_time_link_incognito">使い捨てリンク経由でシークレットモード</string> - <string name="moderated_description">モデレーターによって介入済み</string> + <string name="moderated_description">検閲済</string> <string name="simplex_link_mode_browser_warning">ブラウザでリンクを開くと接続のプライバシーとセキュリティが下がる可能性があります。信頼されないSimpleXリンクは読み込まれません。</string> - <string name="error_joining_group">グループ参加にエラー発生</string> + <string name="error_joining_group">グループ参加でエラー発生</string> <string name="error_sending_message">メッセージ送信にエラー発生</string> <string name="error_accepting_contact_request">連絡先リクエストの承諾にエラー発生</string> - <string name="error_receiving_file">ファイル受信にエラー発生</string> + <string name="error_receiving_file">ファイル受信でエラー発生</string> <string name="error_deleting_contact">連絡先の削除にエラー発生</string> <string name="error_deleting_group">グループ削除にエラー発生</string> <string name="error_deleting_pending_contact_connection">接続待ちの連絡先削除にエラー発生</string> @@ -295,9 +293,9 @@ <string name="auth_log_in_using_credential">ログイン情報でアクセス</string> <string name="auth_confirm_credential">アクセス情報を確認</string> <string name="auth_device_authentication_is_not_enabled_you_can_turn_on_in_settings_once_enabled">端末認証が起動してません。起動したら、設定でSimpleXロックをオンにできます。</string> - <string name="message_delivery_error_desc">恐らくこの連絡先があなたとの接続を削除されました。</string> + <string name="message_delivery_error_desc">この連絡先はあなたとの接続を削除した可能性があります。</string> <string name="for_everybody">全員用</string> - <string name="error_saving_file">ファイル保存にエラー発生</string> + <string name="error_saving_file">ファイル保存でエラー発生</string> <string name="icon_descr_server_status_connected">接続中</string> <string name="icon_descr_server_status_pending">確認待ち</string> <string name="cancel_verb">中止</string> @@ -330,7 +328,7 @@ <string name="callstatus_connecting">発信中…</string> <string name="callstate_ended">終了</string> <string name="opensource_protocol_and_code_anybody_can_run_servers">プロトコル技術とコードはオープンソースで、どなたでもご自分のサーバを運用できます。</string> - <string name="privacy_redefined">プライバシーの基準を新境地に</string> + <string name="privacy_redefined">プライバシーを再定義</string> <string name="how_it_works">技術の説明</string> <string name="make_private_connection">プライベートな接続をする</string> <string name="onboarding_notifications_mode_title">プライベートな通知</string> @@ -391,7 +389,7 @@ <string name="group_member_status_connected">接続中</string> <string name="group_member_status_announced">接続待ち (アナウンス済み)</string> <string name="icon_descr_contact_checked">連絡先が確認済み</string> - <string name="delete_group_question">グループを削除しますか?</string> + <string name="delete_group_question">グループ削除?</string> <string name="delete_link">リンクを削除</string> <string name="group_member_status_group_deleted">グループ削除済み</string> <string name="delete_group_for_all_members_cannot_undo_warning">全員にとってグループが削除されます (※元に戻せません※)!</string> @@ -406,7 +404,7 @@ <string name="conn_level_desc_direct">ダイレクト</string> <string name="receiving_via">経由で受信</string> <string name="create_secret_group_title">シークレットグループを作成する</string> - <string name="group_display_name_field">グループの表示名前</string> + <string name="group_display_name_field">グループ名の入力:</string> <string name="network_status">ネットワーク状況</string> <string name="network_option_ping_interval">PING間合い</string> <string name="network_option_protocol_timeout">プロトコル・タイムアウト</string> @@ -456,8 +454,8 @@ <string name="delete_messages_after">次の期間が経ったら、メッセージを削除:</string> <string name="enable_automatic_deletion_question">自動メッセージ削除を有効にしますか?</string> <string name="remove_passphrase_from_keychain">キーストア (暗証キー保管庫) を削除しますか?</string> - <string name="database_encrypted">データベースは暗号化済み!</string> - <string name="error_encrypting_database">データベース暗号化ににエラー発生</string> + <string name="database_encrypted">データベースは暗号化済!</string> + <string name="error_encrypting_database">データベース暗号化でエラー発生</string> <string name="confirm_new_passphrase">新しいパスフレーズを確認…</string> <string name="encrypt_database_question">データベースを暗号化しますか?</string> <string name="store_passphrase_securely_without_recover">暗証フレーズを失くさないように保管してください。失くすとチャットにアクセスできなくなります。</string> @@ -466,7 +464,7 @@ <string name="restore_passphrase_not_found_desc">キーストア (暗証キー保管庫) に暗証フレーズが見つかりません。入力してください。アプリのデータをバックアップのツールで復元させると暗証フレーズが見つかりかねます。そうではない場合は開発者にご連絡ください。</string> <string name="button_create_group_link">リンクを発行する</string> <string name="info_row_group">グループ</string> - <string name="error_saving_group_profile">グループのプロフィール保存にエラー発生</string> + <string name="error_saving_group_profile">グループのプロフィール保存でエラー発生</string> <string name="feature_enabled">有効</string> <string name="group_members_can_send_disappearing">グループのメンバーが消えるメッセージを送信できます。</string> <string name="ttl_mth">%d月</string> @@ -482,7 +480,7 @@ <string name="failed_to_active_user_title">プロフィール切り替えにエラー発生</string> <string name="error_adding_members">メンバー追加にエラー発生</string> <string name="smp_server_test_create_queue">サーバの待ち行列を作成する</string> - <string name="smp_server_test_delete_queue">待ち行列を削除</string> + <string name="smp_server_test_delete_queue">未配信のメッセージを削除</string> <string name="smp_server_test_disconnect">切断</string> <string name="turn_off_battery_optimization"><![CDATA[利用するには次の画面にてSimpleXに対する <b>SimpleX のバックグラウンドでの実行を許可</b> してください。そうしないと通知が無効になります。]]></string> <string name="database_initialization_error_title">データベースを起動できません。</string> @@ -524,7 +522,6 @@ <string name="mute_chat">ミュート</string> <string name="delete_pending_connection__question">接続待ちの繋がりを削除しますか?</string> <string name="connect_button">接続</string> - <string name="create_one_time_link">使い捨てリンクを発行する</string> <string name="one_time_link">使い捨ての招待リンク</string> <string name="database_passphrase_and_export">データベース暗証フレーズとエキスポート</string> <string name="how_to_use_simplex_chat">使い方</string> @@ -533,11 +530,11 @@ <string name="network_use_onion_hosts_required_desc">接続にオニオンのホストが必要となります。 \n注意: .onion アドレスがないとサーバーに接続できません。</string> <string name="create_address">アドレスを作成</string> - <string name="delete_address__question">アドレスを削除しますか?</string> - <string name="display_name__field">表示の名前:</string> + <string name="delete_address__question">アドレスを削除?</string> + <string name="display_name__field">プロフィール名:</string> <string name="full_name__field">フルネーム:</string> <string name="create_profile_button">作成</string> - <string name="display_name">表示の名前</string> + <string name="display_name">あなたの名前を入力:</string> <string name="colored_text">色付き</string> <string name="callstate_received_answer">応答</string> <string name="decentralized">分散型</string> @@ -569,14 +566,14 @@ <string name="theme_light">ライトテーマ</string> <string name="chat_preferences_default">デフォルト (%s)</string> <string name="prohibit_sending_disappearing_messages">消えるメッセージを使用禁止にする。</string> - <string name="contacts_can_mark_messages_for_deletion">連絡先はメッセージを削除対象とすることができます。あなたには閲覧可能です。</string> + <string name="contacts_can_mark_messages_for_deletion">連絡先はメッセージを削除対象としてマークを付けられます。あなたには閲覧可能です。</string> <string name="only_you_can_send_disappearing">消えるメッセージを送れるのはあなただけです。</string> <string name="prohibit_message_deletion">メッセージの完全削除を使用禁止にする。</string> <string name="prohibit_sending_voice">音声メッセージを使用禁止にする。</string> <string name="feature_cancelled_item">中止されました %s</string> <string name="v4_4_disappearing_messages">消えるメッセージ</string> <string name="v4_5_transport_isolation_descr">チャットのプロフィール (既存設定)、または接続 (β機能設定) による</string> - <string name="v4_5_multiple_chat_profiles_descr">異なった名前、アバター、トランスポート隔離。</string> + <string name="v4_5_multiple_chat_profiles_descr">別名、アバター、分離送信。</string> <string name="v4_4_french_interface">フランス語UI</string> <string name="v4_5_message_draft">メッセージの下書き</string> <string name="v4_5_reduced_battery_usage_descr">まだまだ改善してまいります!</string> @@ -584,15 +581,15 @@ <string name="v4_5_message_draft_descr">添付を含めて、下書きを保存する。</string> <string name="v4_5_private_filenames">プライベートなファイル名</string> <string name="v4_5_reduced_battery_usage">電池使用量低減</string> - <string name="error_removing_member">メンバー除名にエラー発生</string> - <string name="conn_level_desc_indirect">関節 (%1$s)</string> + <string name="error_removing_member">メンバー削除でエラー発生</string> + <string name="conn_level_desc_indirect">間接 (%1$s)</string> <string name="incognito">シークレットモード</string> <string name="incognito_info_protects">シークレット モードでは、連絡先ごとに新しいランダムなプロファイルを使用してプライバシーを保護します。</string> <string name="chat_preferences_no">いいえ</string> <string name="chat_preferences_on">オン</string> <string name="direct_messages">ダイレクトメッセージ</string> <string name="timed_messages">消えるメッセージ</string> - <string name="disappearing_prohibited_in_this_chat">このチャットでは消えるメッセージが使用禁止です。</string> + <string name="disappearing_prohibited_in_this_chat">このチャットでは消えるメッセージが無効です。</string> <string name="prohibit_direct_messages">メンバー間のダイレクトメッセージを使用禁止にする。</string> <string name="prohibit_sending_disappearing">消えるメッセージを使用禁止にする。</string> <string name="ttl_s">%d秒</string> @@ -605,7 +602,7 @@ <string name="import_database_question">チャットのデータベースを読み込みますか?</string> <string name="chat_database_imported">チャットのデータベースが読み込まれました。</string> <string name="error_deleting_database">チャットデータベース削除にエラー発生</string> - <string name="error_importing_database">チャットデータベースの読み込みにエラー発生</string> + <string name="error_importing_database">チャットデータベースの読み込みでエラー発生</string> <string name="import_database_confirmation">読み込む</string> <string name="restart_the_app_to_use_imported_chat_database">読み込んだデータベースを利用するにはアプリを再起動する必要があります。</string> <string name="delete_chat_profile_question">チャットのプロフィールを削除しますか?</string> @@ -613,17 +610,17 @@ <string name="files_and_media_section">ファイルとメディア</string> <string name="error_changing_message_deletion">設定変更にエラー発生</string> <string name="notifications_will_be_hidden">アプリが起動中のみに通知が出ます!</string> - <string name="encrypted_database">暗号化済みデータベース</string> + <string name="encrypted_database">暗号化データベース</string> <string name="keychain_error">キーチェーンのエラー</string> <string name="store_passphrase_securely">暗証フレーズを失くさないように保管してください。失くすと変更できなくなります。</string> - <string name="error_with_info">エラー: %s</string> + <string name="error_with_info">エラー: %s</string> <string name="restore_database_alert_desc">データベースのバックアップで復旧する際に前の暗証フレーズを入力してください。行われたら元に戻せません。</string> <string name="icon_descr_add_members">メンバーを招待する</string> <string name="rcv_group_event_member_left">脱退しました。</string> <string name="rcv_group_event_changed_member_role">%s の役割を %s に変えました。</string> <string name="rcv_group_event_changed_your_role">役割を %s に変えました。</string> <string name="rcv_group_event_member_added">招待された %1$s</string> - <string name="snd_conn_event_switch_queue_phase_changing_for_member">アドレスを変更いたします: %s</string> + <string name="snd_conn_event_switch_queue_phase_changing_for_member">アドレスを変更しています: %s</string> <string name="group_member_role_owner">オーナー</string> <string name="group_member_status_connecting">接続待ち</string> <string name="icon_descr_expand_role">役割の選択を拡大</string> @@ -647,7 +644,7 @@ <string name="theme">テーマ</string> <string name="voice_messages">音声メッセージ</string> <string name="app_name">SimpleX</string> - <string name="you_will_join_group">このリンクのグループに参加し、そのメンバーに繋がります。</string> + <string name="you_will_join_group">グループメンバー全員と接続する。</string> <string name="connected_to_server_to_receive_messages_from_contact">この連絡先から受信するメッセージのサーバに既に接続してます。</string> <string name="sending_files_not_yet_supported">ファイル送信機能がまだ実装されてません</string> <string name="trying_to_connect_to_server_to_receive_messages">このコンタクトから受信するメッセージのサーバに接続しようとしてます。</string> @@ -676,7 +673,7 @@ <string name="icon_descr_speaker_off">スピーカーオフ</string> <string name="your_chat_database">あなたのチャットデータベース</string> <string name="stop_chat_confirmation">停止</string> - <string name="stop_chat_to_enable_database_actions">データベース操作をするにはチャットを閉じてからです。</string> + <string name="stop_chat_to_enable_database_actions">データベース操作をするにはチャットを停止する必要があります。</string> <string name="simplex_link_contact">SimpleX連絡先アドレス</string> <string name="simplex_link_invitation">SimpleX使い捨て招待リンク</string> <string name="description_via_contact_address_link">連絡先アドレスリンク経由</string> @@ -700,7 +697,7 @@ <string name="group_preview_you_are_invited">グループ招待が届きました</string> <string name="your_chats">チャット</string> <string name="text_field_set_contact_placeholder">連絡先を設定…</string> - <string name="waiting_for_file">ファイル待ち</string> + <string name="waiting_for_file">ファイルを待機中</string> <string name="switch_receiving_address_question">受信アドレスを変えますか?</string> <string name="send_verb">送信する</string> <string name="send_live_message_desc">ライブメッセージを送信 (入力しながら宛先の画面で更新される)</string> @@ -708,7 +705,7 @@ <string name="connect_via_link_or_qr_from_clipboard_or_in_person">(クリップボードから読み込むか、貼り付ける)</string> <string name="thank_you_for_installing_simplex">SimpleX Chatをご利用いただきありがとうございます!</string> <string name="use_camera_button">カメラ</string> - <string name="you_accepted_connection">繋がりを承認しました</string> + <string name="you_accepted_connection">接続を承認しました</string> <string name="you_invited_a_contact">連絡先に招待を送りました</string> <string name="connection_you_accepted_will_be_cancelled">承認ずみの接続がキャンセルされます!</string> <string name="contact_you_shared_link_with_wont_be_able_to_connect">あなたからリンクを受けた連絡先が接続できなくなります!</string> @@ -719,7 +716,7 @@ <string name="you_will_be_connected_when_group_host_device_is_online">グループのホスト端末がオンラインになったら、接続されます。後でチェックするか、しばらくお待ちください。</string> <string name="you_will_be_connected_when_your_contacts_device_is_online">連絡先がオンラインになったら、接続されます。後でチェックするか、しばらくお待ちください。</string> <string name="your_chat_profile_will_be_sent_to_your_contact">あなたのチャットプロフィールが -\n連絡相手に送られます。</string> +\n連絡先に公開されます。</string> <string name="share_invitation_link">ワンタイムリンクを送る</string> <string name="scan_code">コードを読み込む</string> <string name="scan_code_from_contacts_app">連絡相手のアプリからセキュリティコードを読み込む</string> @@ -742,9 +739,9 @@ <string name="network_use_onion_hosts">.onionホストを使う</string> <string name="network_use_onion_hosts_prefer">利用可能時に</string> <string name="network_session_mode_transport_isolation">トランスポート隔離</string> - <string name="save_and_notify_contact">保存して、連絡先にに知らせる</string> + <string name="save_and_notify_contact">保存して、連絡先に公開</string> <string name="your_current_profile">現在のプロフィール</string> - <string name="save_and_notify_contacts">保存して、連絡先にに知らせる</string> + <string name="save_and_notify_contacts">保存して、連絡先に公開</string> <string name="the_messaging_and_app_platform_protecting_your_privacy_and_security">あなたのプライバシーとセキュリティを守るメッセージとアプリのプラットフォーム</string> <string name="we_do_not_store_contacts_or_messages_on_servers">連絡先情報と届けたメッセージをサーバに保存することは一切ありません。</string> <string name="you_control_your_chat">あなたのチャットはあなたが決めます!</string> @@ -754,7 +751,7 @@ <string name="secret_text">シークレット</string> <string name="strikethrough_text">取り消し線</string> <string name="callstate_starting">接続中…</string> - <string name="next_generation_of_private_messaging">次世代のプライバシー・メッセンジャー</string> + <string name="next_generation_of_private_messaging">次世代のプライベートメッセンジャー</string> <string name="you_control_servers_to_receive_your_contacts_to_send"><![CDATA[あなたがメッセージの<b>受信</b>サーバを決められます。あなたの連絡先が同じく、自分に対する受信サーバを決められます。]]></string> <string name="icon_descr_video_call">ビデオ通話</string> <string name="onboarding_notifications_mode_off">アプリが稼働中に</string> @@ -791,7 +788,7 @@ <string name="member_role_will_be_changed_with_notification">役割が「%s」となります。グループの全員に通知が出ます。</string> <string name="conn_stats_section_title_servers">サーバ</string> <string name="member_role_will_be_changed_with_invitation">役割が「%s」となります。メンバーに新しい招待が届きます。</string> - <string name="group_is_decentralized">グループは完全分散型で、メンバーしか内容を見れません。</string> + <string name="group_is_decentralized">非中央集権型で、メンバーのみ閲覧可能。</string> <string name="network_options_save">保存</string> <string name="update_network_settings_question">ネットワーク設定を更新しますか?</string> <string name="updating_settings_will_reconnect_client_to_all_servers">設定を更新すると、全サーバにクライントの再接続が行われます。</string> @@ -805,15 +802,15 @@ <string name="v4_2_security_assessment">セキュリティ評価</string> <string name="whats_new">新着情報</string> <string name="v4_2_security_assessment_desc">SimpleX ChatはTrail of Bitsによるセキュリティ監査を受けました。</string> - <string name="v4_2_auto_accept_contact_requests_desc">任意的な歓迎メッセージで</string> + <string name="v4_2_auto_accept_contact_requests_desc">歓迎メッセージを追加できます。</string> <string name="v4_5_italian_interface_descr">ユーザーの皆様に感謝いたします!Weblateにて貢献できます!</string> <string name="v4_4_verify_connection_security">接続のセキュリティを確認</string> <string name="error_smp_test_failed_at_step">テストが次のステップで失敗しました:%s</string> <string name="ntf_channel_messages">SimpleX Chatメッセージ</string> <string name="ntf_channel_calls">SimpleX Chat通話</string> <string name="settings_notification_preview_mode_title">プレビューを表示</string> - <string name="notifications_mode_periodic">定期的に起動</string> - <string name="notifications_mode_off">アプリがアクティブ時に実行</string> + <string name="notifications_mode_periodic">定期的に更新</string> + <string name="notifications_mode_off">アプリがアクティブ時に通知を受ける</string> <string name="icon_descr_sent_msg_status_sent">送信済み</string> <string name="you_have_no_chats">あなたはチャットがありません。</string> <string name="share_message">メッセージを送る…</string> @@ -828,36 +825,36 @@ <string name="star_on_github">GithubでStar</string> <string name="your_profile_is_stored_on_device_and_shared_only_with_contacts_simplex_cannot_see_it">あなたのプロフィールはご自分の端末に保存され、あなたの連絡先のみに共有されます。 SimpleXのサーバには開示されません。</string> <string name="your_calls">あなたの通話</string> - <string name="integrity_msg_skipped">%1$d飛ばしたメッセージ</string> + <string name="integrity_msg_skipped">%1$dスキップしたメッセージ</string> <string name="send_link_previews">リンクのプレビューを送信</string> <string name="set_password_to_export">暗証フレーズを設定してからエキスポート</string> <string name="stop_chat_question">チャットを閉じますか?</string> <string name="save_passphrase_in_keychain">暗証フレーズをキーストア (暗証キー保管庫) に保存</string> - <string name="wrong_passphrase">データベースの暗証フレーズが違います</string> + <string name="wrong_passphrase">不正なパスフレーズ</string> <string name="unknown_error">不明なエラー</string> <string name="save_passphrase_and_open_chat">暗証フレーズをを保存して、チャットを開始</string> <string name="unknown_database_error_with_info">不明なデータベースのエラー: %s</string> - <string name="wrong_passphrase_title">暗証フレーズが違います!</string> + <string name="wrong_passphrase_title">不正なパスフレーズです!</string> <string name="you_are_invited_to_group">グループ招待が届きました</string> <string name="network_option_seconds_label">秒</string> <string name="network_option_tcp_connection_timeout">TCP接続タイムアウト</string> <string name="save_group_profile">保存グループのプロフィール</string> <string name="v4_3_irreversible_message_deletion_desc">連絡先がメッセージの完全削除を許可できます。</string> <string name="failed_to_create_user_duplicate_desc">同じ表示名前のチャットプロフィールが既にあります。別のを選んでください。</string> - <string name="smp_server_test_secure_queue">待ち行列セキュリティ確認</string> + <string name="smp_server_test_secure_queue">セキュアな未送信メッセージ</string> <string name="database_initialization_error_desc">データベースが正しく稼働してません。詳細はタップにて</string> <string name="notification_preview_mode_message_desc">連絡先とメッセージを表示</string> <string name="la_notice_to_protect_your_information_turn_on_simplex_lock_you_will_be_prompted_to_complete_authentication_before_this_feature_is_enabled">あなたのデータを守るために、SimpleXロックをオンにしてください。 \nオンにするには、認証ステップが行われます。</string> <string name="la_notice_turn_on">オンにする</string> <string name="auth_unlock">ロック解除</string> - <string name="save_verb">保存する</string> + <string name="save_verb">保存</string> <string name="reveal_verb">開示する</string> <string name="tap_to_start_new_chat">タップして新しいチャットを始める</string> <string name="image_decoding_exception_desc">画像が解読できません。別のイメージで試すか、開発者に伝えてください。</string> - <string name="icon_descr_waiting_for_image">画像待ち</string> - <string name="waiting_for_image">画像待ち</string> - <string name="contact_sent_large_file">向こうが最上限の大きさを超えるファイルを送ろうとしました (%1$s)。</string> + <string name="icon_descr_waiting_for_image">画像を待機中</string> + <string name="waiting_for_image">画像を待機中</string> + <string name="contact_sent_large_file">相手が上限を超える容量のファイルを送ろうとしました (%1$s)。</string> <string name="voice_messages_prohibited">音声メッセージは使用禁止です!</string> <string name="add_contact_or_create_group">新しいチャットを始める</string> <string name="you_can_connect_to_simplex_chat_founder"><![CDATA[<font color="#0088ff">SimpleX Chatの開発者と繋がれば、質問したり、速報を受けたりすることができます</font>。]]></string> @@ -865,18 +862,18 @@ <string name="chat_help_tap_button">ボタンをタップ</string> <string name="unmute_chat">ミュート解除</string> <string name="set_contact_name">連絡先を設定</string> - <string name="contact_wants_to_connect_with_you">はあなたと繋がりたいです!</string> + <string name="contact_wants_to_connect_with_you">あなたと接続を希望しています!</string> <string name="you_can_also_connect_by_clicking_the_link"><![CDATA[リンクをクリックすることでも接続できます。ブラウザが起動すれば <b>Open in mobile app (アプリで開く)</b>ボタンをクリックしてください。]]></string> - <string name="your_chat_profiles">あなたのチャットプロフィール</string> + <string name="your_chat_profiles">チャットプロフィール</string> <string name="smp_servers_scan_qr">サーバのQRコードを読み込む</string> <string name="smp_servers_test_some_failed">テストに失敗したサーバがあります:</string> <string name="use_simplex_chat_servers__question">SimpleX Chatサーバを使いますか?</string> <string name="using_simplex_chat_servers">SimpleX Chatを使っています。</string> <string name="share_link">リンクを送る</string> <string name="core_simplexmq_version">simplexmq: バージョン%s (%2s)</string> - <string name="callstate_waiting_for_answer">応答待ち…</string> - <string name="callstate_waiting_for_confirmation">確認待ち…</string> - <string name="first_platform_without_user_ids">世界初のユーザーIDのないプラットフォーム|設計も元からプライベート</string> + <string name="callstate_waiting_for_answer">応答を待機中…</string> + <string name="callstate_waiting_for_confirmation">確認を待機中…</string> + <string name="first_platform_without_user_ids">世界初のユーザーIDのないプラットフォーム - プライバシーに配慮した設計</string> <string name="use_chat">チャット</string> <string name="contact_wants_to_connect_via_call">%1$sは次の方法であなたと繋がりたいです:</string> <string name="video_call_no_encryption">ビデオ通話 (非エンドツーエンド暗号化)</string> @@ -904,7 +901,7 @@ <string name="smp_servers_test_servers">テストサーバ</string> <string name="switch_receiving_address_desc">受信アドレスは別のサーバーに変更されます。アドレス変更は送信者がオンラインになった後に完了します。</string> <string name="to_protect_privacy_simplex_has_ids_for_queues">あなたのプライバシーを守るために、他のアプリと違って、ユーザーIDの変わりに SimpleX メッセージ束毎にIDを配布し、各連絡先が別々と扱います。</string> - <string name="group_main_profile_sent">あなたのチャットプロフィールが他のグループメンバーに送られます。</string> + <string name="group_main_profile_sent">あなたのチャットプロフィールが他のグループメンバーに公開されます。</string> <string name="to_verify_compare">エンドツーエンド暗号化を確認するには、ご自分の端末と連絡先の端末のコードを比べます (スキャンします)。</string> <string name="trying_to_connect_to_server_to_receive_messages_with_error">このコンタクトから受信するメッセージのサーバに接続しようとしてます。(エラー: %1$s)。</string> <string name="connection_error_auth_desc">使用済みリンク、または連絡先による接続の削除ではなければ、バッグの可能性があります。開発者にお伝えください。 @@ -916,7 +913,7 @@ <string name="image_descr_simplex_logo">SimpleXロゴ</string> <string name="you_need_to_allow_to_send_voice">音声メッセージを送るには、連絡相手からの音声メッセージを許可しなければなりません。</string> <string name="you_must_use_the_most_recent_version_of_database">あなたの最新データベースを1つの端末にしか使わなければ、一部の連絡先からメッセージが届きかねます。</string> - <string name="you_are_already_connected_to_vName_via_this_link">既に繋がってます: %1$s</string> + <string name="you_are_already_connected_to_vName_via_this_link">すでに接続済です: %1$s</string> <string name="alert_title_cant_invite_contacts_descr">シークレットモードのプロフィールでこのグループに参加しています。メインのプロフィールを守るために、招待することができません。</string> <string name="description_you_shared_one_time_link">使い捨てリンクを送りました</string> <string name="profile_will_be_sent_to_contact_sending_link">リンクを送ってくれた連絡先にあなたのプロフィールを送ります。</string> @@ -927,7 +924,7 @@ <string name="incognito_random_profile">あなたのランダム・プロフィール</string> <string name="v4_3_voice_messages">音声メッセージ</string> <string name="settings_section_title_socks">SOCKSプロキシ</string> - <string name="stop_chat_to_export_import_or_delete_chat_database">データベースのエキスポート、読み込み、削除するにはチャットを閉じてからです。チャットを閉じると送受信ができなくなります。</string> + <string name="stop_chat_to_export_import_or_delete_chat_database">データベースのエキスポート、読み込み、削除するにはチャット機能を停止する必要があります。チャット機能を停止すると送受信ができなくなります。</string> <string name="delete_chat_profile_action_cannot_be_undone_warning">あなたのプロフィール、連絡先、メッセージ、ファイルが完全削除されます (※元に戻せません※)。</string> <string name="update_database_passphrase">データベース暗証フレーズを更新</string> <string name="save_archive">アーカイブを保存</string> @@ -947,7 +944,6 @@ <string name="la_lock_mode_passcode">パスコード入力</string> <string name="la_auth_failed">認証失敗</string> <string name="la_enter_app_passcode">パスコードを入力</string> - <string name="cant_delete_user_profile">ユーザープロフィールが削除できません。</string> <string name="la_mode_system">システム</string> <string name="change_lock_mode">ロックモードを変更</string> <string name="v4_6_chinese_spanish_interface">中国語とスペイン語UI</string> @@ -964,7 +960,7 @@ <string name="read_more_in_user_guide_with_link"><![CDATA[<font color="#0088ff">ユーザーガイド</font>で詳細を見る]]></string> <string name="simplex_address">SimpleXアドレス</string> <string name="network_proxy_port">ポート %d</string> - <string name="enter_welcome_message_optional">ウェルカムメッセージを入力…(オプション)</string> + <string name="enter_welcome_message_optional">ウェルカムメッセージを入力…(任意)</string> <string name="save_settings_question">設定を保存しますか?</string> <string name="confirm_passcode">パスコードを確認</string> <string name="la_mode_passcode">パスコード</string> @@ -976,7 +972,7 @@ <string name="one_time_link_short">使い捨てのリンク</string> <string name="address_section_title">アドレス</string> <string name="color_background">背景色</string> - <string name="confirm_password">パスワードを確認</string> + <string name="confirm_password">ご確認のため、再度ご入力ください。</string> <string name="settings_section_title_experimenta">β機能</string> <string name="decryption_error">復号化エラー</string> <string name="button_add_welcome_message">ウェルカムメッセージを追加</string> @@ -985,11 +981,11 @@ <string name="database_upgrade">データベースアップグレード</string> <string name="audio_video_calls">音声/ビデオ通話</string> <string name="calls_prohibited_with_this_contact">音声/ビデオ通話は禁止されています。</string> - <string name="feature_received_prohibited">禁帯出</string> + <string name="feature_received_prohibited">受信拒絶</string> <string name="ensure_xftp_server_address_are_correct_format_and_unique">XFTPサーバーのアドレスが正しい形式で、行で区切られており、重複していないことを確認してください。</string> <string name="smp_server_test_delete_file">ファイルの削除</string> <string name="icon_descr_waiting_for_video">ビデオ待機中</string> - <string name="waiting_for_video">Waiting for video</string> + <string name="waiting_for_video">ビデオを待機中</string> <string name="group_welcome_title">ウェルカムメッセージ</string> <string name="host_verb">ホスト</string> <string name="lock_after">自動ロックまでの時間</string> @@ -1043,7 +1039,7 @@ <string name="stop_sharing">共有を停止</string> <string name="invite_friends">友人を招待する</string> <string name="you_can_create_it_later">後からでも作成できます</string> - <string name="password_to_show">パスワードを表示する</string> + <string name="password_to_show">ここにパスワードを入力してください。</string> <string name="authentication_cancelled">認証がキャンセルされました</string> <string name="share_address">アドレスを共有する</string> <string name="theme_simplex">SimpleX</string> @@ -1064,9 +1060,9 @@ <string name="v5_0_large_files_support">1GBまでのビデオとファイル</string> <string name="alert_text_decryption_error_n_messages_failed_to_decrypt">%1$d メッセージの復号化に失敗しました。</string> <string name="alert_text_decryption_error_too_many_skipped">%1$d メッセージをスキップしました</string> - <string name="error_loading_smp_servers">SMP サーバーのロード中にエラーが発生しました</string> - <string name="error_saving_user_password">ユーザーパスワード保存エラー</string> - <string name="error_loading_xftp_servers">XFTP サーバーのロード中にエラーが発生しました</string> + <string name="error_loading_smp_servers">SMPサーバーのロード中にエラーが発生しました</string> + <string name="error_saving_user_password">ユーザーパスワードの保存中にエラー発生</string> + <string name="error_loading_xftp_servers">XFTPサーバーのロード中にエラーが発生しました</string> <string name="export_theme">テーマのエクスポート</string> <string name="revoke_file__message">ファイルはサーバーから削除されます。</string> <string name="if_you_cant_meet_in_person">直接会えない場合は、ビデオ通話で QR コードを表示するか、リンクを共有してください。</string> @@ -1086,9 +1082,9 @@ <string name="initial_member_role">初期の役割</string> <string name="alert_text_fragment_encryption_out_of_sync_old_database">古いデータベースのバックアップを使用した場合に発生する可能性があります。</string> <string name="v4_6_chinese_spanish_interface_descr">ユーザーに感謝します – Weblate 経由で貢献してください!</string> - <string name="v4_6_audio_video_calls_descr">Bluetooth およびその他の改善をサポートします。</string> + <string name="v4_6_audio_video_calls_descr">Bluetoothのサポートおよびその他の機能も改善されました。</string> <string name="relay_server_if_necessary">中継サーバーは必要な場合にのみ使用されます。 別の当事者があなたの IP アドレスを監視できます。</string> - <string name="stop_sharing_address">アドレスの共有を停止しますか?</string> + <string name="stop_sharing_address">アドレス共有の停止?</string> <string name="color_sent_message">送信</string> <string name="color_received_message">受信したメッセージ</string> <string name="alert_text_msg_bad_hash">以前のメッセージとハッシュ値が異なります。</string> @@ -1104,20 +1100,18 @@ <string name="downgrade_and_open_chat">ダウングレードしてチャットを開く</string> <string name="la_please_remember_to_store_password">パスワードを覚えるか、安全に保管してください。失われたパスワードを回復する方法はありません。</string> <string name="smp_server_test_download_file">ファイルをダウンロード</string> - <string name="you_can_hide_or_mute_user_profile">ユーザープロフィールを非表示またはミュートすることができます(メニューを長押し)。</string> + <string name="you_can_hide_or_mute_user_profile">ユーザープロフィールを非表示またはミュートすることができます(名前を長押し)。</string> <string name="v4_6_group_moderation">グループのモデレーション</string> <string name="email_invite_body">こんにちは! \nSimpleX Chatの招待が届いています: %s</string> <string name="v4_6_group_welcome_message">グループのウェルカムメッセージ</string> - <string name="tap_to_activate_profile">タップしてプロフィールを有効化する。</string> + <string name="tap_to_activate_profile">タップでプロフィールを切り替え</string> <string name="profile_password">プロフィールのパスワード</string> <string name="v4_6_hidden_chat_profiles_descr">チャットのプロフィールをパスワードで保護します!</string> <string name="group_member_role_observer">オブザーバー</string> <string name="v5_0_large_files_support_descr">送信者がオンラインになるまでの待ち時間がなく、速い!</string> <string name="v5_0_app_passcode">アプリのパスコード</string> <string name="v5_0_app_passcode_descr">システム認証の代わりに設定します。</string> - <string name="should_be_at_least_one_visible_profile">少なくとも1つのユーザープロフィールが表示されている必要があります。</string> - <string name="should_be_at_least_one_profile">少なくとも1つのユーザープロファイルが必要です。</string> <string name="make_profile_private">プロフィールを非表示にできます!</string> <string name="relay_server_protects_ip">リレー サーバーは IP アドレスを保護しますが、通話時間は監視されます。</string> <string name="share_address_with_contacts_question">アドレスを連絡先と共有しますか\?</string> @@ -1127,9 +1121,9 @@ <string name="callstate_received_confirmation">確認を受け取りました…</string> <string name="feature_offered_item_with_param">提供された %s: %2s</string> <string name="error_xftp_test_server_auth">アップロードにはサーバーの認証が必要です。パスワードを確認してください</string> - <string name="moderate_verb">モデレート</string> + <string name="moderate_verb">検閲</string> <string name="icon_descr_video_asked_to_receive">ビデオの受信を要求されました</string> - <string name="moderated_item_description">モデレートされた %s</string> + <string name="moderated_item_description">%sにより検閲</string> <string name="error_updating_user_privacy">ユーザーのプライバシーの更新エラー</string> <string name="moderate_message_will_be_marked_warning">メッセージはすべてのメンバーに対してモデレート済みとしてマークされます。</string> <string name="hide_profile">非表示のプロフィール</string> @@ -1156,16 +1150,16 @@ <string name="mtr_error_different">アプリ/データベースの異なる移行: %s / %s</string> <string name="user_hide">非表示</string> <string name="user_unhide">表示にする</string> - <string name="hidden_profile_password">非表示のプロフィール パスワード</string> + <string name="hidden_profile_password">非表示プロフィールのパスワード</string> <string name="show_dev_options">表示する:</string> <string name="create_address_and_let_people_connect">人々があなたとつながるためのアドレスを作成します。</string> <string name="error_setting_address">アドレス設定エラー</string> <string name="you_can_share_your_address">アドレスをリンクまたは QR コードとして共有すると、誰でもあなたに接続できます。</string> <string name="you_wont_lose_your_contacts_if_delete_address">後でアドレスを削除しても、連絡先が失われることはありません。</string> - <string name="your_contacts_will_remain_connected">連絡先は接続されたままになります。</string> - <string name="all_your_contacts_will_remain_connected_update_sent">すべての連絡先は接続されたままになります。 プロフィールの更新が連絡先に送信されます。</string> + <string name="your_contacts_will_remain_connected">連絡先との接続がそのまま続きます。</string> + <string name="all_your_contacts_will_remain_connected_update_sent">連絡先との接続がそのまま続きます。 プロフィールの更新が連絡先に共有されます。</string> <string name="create_simplex_address">SimpleX のアドレスを作成</string> - <string name="share_with_contacts">連絡先と共有する</string> + <string name="share_with_contacts">連絡先に公開する</string> <string name="profile_update_will_be_sent_to_contacts">プロフィールの更新は連絡先に送信されます。</string> <string name="dont_create_address">アドレスを作成しない</string> <string name="email_invite_subject">SimpleXチャットで会話しよう</string> @@ -1173,7 +1167,7 @@ <string name="save_profile_password">プロフィールのパスワードを保存する</string> <string name="you_can_share_this_address_with_your_contacts">このアドレスを連絡先と共有して、%s に接続できるようにすることができます。</string> <string name="save_and_update_group_profile">グループプロフィールの保存と更新</string> - <string name="to_reveal_profile_enter_password">非表示のプロフィールを表示するには、チャット プロフィール ページの検索フィールドに完全なパスワードを入力します。</string> + <string name="to_reveal_profile_enter_password">非表示のプロフィールを戻すには、プロフィールページの検索欄にパスワードを入力します。</string> <string name="hide_dev_options">非表示 :</string> <string name="delete_chat_profile">チャット プロフィールを削除する</string> <string name="delete_profile">プロフィールの削除</string> @@ -1208,13 +1202,13 @@ <string name="share_text_database_id">データベースID: %d</string> <string name="share_text_deleted_at">削除されました: %s</string> <string name="info_row_disappears_at">に消えます</string> - <string name="info_row_moderated_at">モデレーターによって介入済み</string> + <string name="info_row_moderated_at">検閲済</string> <string name="share_text_received_at">受信: %s</string> <string name="share_text_updated_at">レコード更新日時: %s</string> <string name="share_text_sent_at">送信日時: %s</string> <string name="item_info_current">(現在)</string> <string name="share_text_disappears_at">%s :に消えます</string> - <string name="share_text_moderated_at">モデレーターによって介入済み: %s</string> + <string name="share_text_moderated_at">検閲済: %s</string> <string name="current_version_timestamp">%s (現在)</string> <string name="both_you_and_your_contact_can_add_message_reactions">自分も相手もメッセージへのリアクションを追加できます。</string> <string name="message_reactions">メッセージへのリアクション</string> @@ -1247,14 +1241,14 @@ <string name="v5_1_custom_themes_descr">カラーテーマをカスタマイズして共有することができます。</string> <string name="whats_new_thanks_to_users_contribute_weblate">ユーザーに感謝します – Weblate 経由で貢献してください!</string> <string name="v5_1_message_reactions_descr">ついに、私たちはそれらを手に入れました! 🚀</string> - <string name="v5_1_better_messages">より良いメッセージ</string> + <string name="v5_1_better_messages">改善されたメッセージ機能</string> <string name="la_mode_off">オフ</string> <string name="choose_file_title">ファイルを選択</string> <string name="unfavorite_chat">お気に入りを解除</string> <string name="favorite_chat">お気に入り</string> - <string name="receipts_contacts_override_enabled">Sending receipts is enabled for %d contacts</string> + <string name="receipts_contacts_override_enabled">配信通知の送信が%d件の連絡先で有効になっています</string> <string name="receipts_contacts_enable_for_all">すべて有効</string> - <string name="receipts_contacts_override_disabled">Sending receipts is disabled for %d contacts</string> + <string name="receipts_contacts_override_disabled">配信通知の送信が %d件の連絡先で無効になっています</string> <string name="receipts_contacts_disable_for_all">すべて無効</string> <string name="settings_shutdown">終了</string> <string name="conn_event_ratchet_sync_started">暗号化に同意しています…</string> @@ -1268,7 +1262,7 @@ <string name="rcv_conn_event_verification_code_reset">セキュリティコードが変更されました</string> <string name="fix_connection_confirm">修正</string> <string name="fix_connection_question">接続を修正しますか\?</string> - <string name="renegotiate_encryption">暗号化の再ネゴシエート</string> + <string name="renegotiate_encryption">暗号化された再接続</string> <string name="allow_to_send_files">ファイルやメディアの送信を許可</string> <string name="prohibit_sending_files">ファイルやメディアの送信を禁止します。</string> <string name="v5_2_fix_encryption">接続を維持</string> @@ -1298,13 +1292,13 @@ <string name="v5_2_fix_encryption_descr">バックアップの復元後に暗号化を修正します。</string> <string name="snd_conn_event_ratchet_sync_started">暗号化に同意しています: %s</string> <string name="conn_event_ratchet_sync_agreed">暗号化に同意しました</string> - <string name="receipts_contacts_title_disable">Disable receipts\?</string> + <string name="receipts_contacts_title_disable">配信通知を無効?</string> <string name="fix_connection_not_supported_by_contact">連絡先による修正はサポートされていません</string> <string name="fix_connection_not_supported_by_group_member">グループメンバーによる修正はサポートされていません</string> <string name="receipts_section_contacts">連絡先</string> <string name="receipts_section_description_1">これらは連絡先とグループの設定が優先されます。</string> <string name="receipts_section_description">これらの設定は現在のプロファイル用です</string> - <string name="receipts_contacts_title_enable">Enable receipts\?</string> + <string name="receipts_contacts_title_enable">配信通知を有効?</string> <string name="sender_at_ts">%s : %s</string> <string name="fix_connection">接続を修正</string> <string name="files_and_media">ファイルとメディア</string> @@ -1314,10 +1308,10 @@ <string name="no_history">履歴はありません</string> <string name="abort_switch_receiving_address_confirm">中止</string> <string name="sync_connection_force_desc">暗号化は機能しており、新しい暗号化への同意は必要ありません。接続エラーが発生する可能性があります!</string> - <string name="sync_connection_force_question">暗号化を再ネゴシエートしますか\?</string> + <string name="sync_connection_force_question">暗号化された再接続?</string> <string name="in_reply_to">返信先</string> <string name="only_owners_can_enable_files_and_media">ファイルやメディアを有効にできるのは、グループオーナーだけです。</string> - <string name="sync_connection_force_confirm">再ネゴシエート</string> + <string name="sync_connection_force_confirm">再接続</string> <string name="settings_restart_app">再起動</string> <string name="connect_via_link_incognito">シークレットモードで接続</string> <string name="turn_off_battery_optimization_button">許可</string> @@ -1334,10 +1328,10 @@ <string name="system_restricted_background_in_call_desc">アプリはバックグラウンドで1分経過すると終了します。</string> <string name="system_restricted_background_in_call_warn"><![CDATA[バックグラウンドで通話を行うには、アプリの設定で<b>アプリのバッテリー使用量</b> / <b>制限なし</b> を選択してください。]]></string> <string name="connect__your_profile_will_be_shared">あなたのプロフィール %1$s が共有されます。</string> - <string name="receipts_groups_title_enable">Enable receipts for groups\?</string> - <string name="receipts_groups_title_disable">Disable receipts for groups\?</string> - <string name="receipts_groups_override_enabled">Sending receipts is enabled for %d groups</string> - <string name="receipts_groups_override_disabled">Sending receipts is disabled for %d groups</string> + <string name="receipts_groups_title_enable">グループの配信通知を有効?</string> + <string name="receipts_groups_title_disable">グループの配信通知を無効?</string> + <string name="receipts_groups_override_enabled">配信通知の送信が%d件のグループで有効になっています</string> + <string name="receipts_groups_override_disabled">配信通知の送信が%d件のグループで無効になっています</string> <string name="send_receipts_disabled">無効</string> <string name="system_restricted_background_in_call_title">バックグラウンド通話なし</string> <string name="paste_the_link_you_received_to_connect_with_your_contact">受信したリンクを貼り付け、連絡先に接続する。</string> @@ -1352,25 +1346,25 @@ <string name="receipts_groups_disable_for_all">すべてのグループで無効にする</string> <string name="privacy_message_draft">メッセージの下書き</string> <string name="privacy_show_last_messages">最新のメッセージを表示</string> - <string name="send_receipts">Send receipts</string> + <string name="send_receipts">配信通知の送信</string> <string name="rcv_group_event_n_members_connected">%s, %s および %d 人の他のメンバーが接続しています。</string> <string name="rcv_group_event_3_members_connected">%s, %s と %s は接続中</string> <string name="in_developing_desc">この機能はまだサポートされていません。次のリリースをお試しください。</string> <string name="receipts_contacts_enable_keep_overrides">有効にする(設定の優先を維持)</string> - <string name="receipts_groups_disable_keep_overrides">無効にする(グループの設定の優先を維持)</string> + <string name="receipts_groups_disable_keep_overrides">無効にする (グループの上書きを維持)</string> <string name="receipts_groups_enable_keep_overrides">有効にする(グループの設定の優先を維持)</string> - <string name="receipts_contacts_disable_keep_overrides">無効にする(設定の優先を維持)</string> + <string name="receipts_contacts_disable_keep_overrides">無効化(設定の優先を維持)</string> <string name="v5_2_disappear_one_message_descr">会話中に無効になっている場合でも。</string> - <string name="v5_2_message_delivery_receipts">Message delivery receipts!</string> - <string name="delivery_receipts_title">Delivery receipts!</string> - <string name="sending_delivery_receipts_will_be_enabled_all_profiles">Sending delivery receipts will be enabled for all contacts in all visible chat profiles.</string> - <string name="message_delivery_error_title">Message delivery error</string> - <string name="send_receipts_disabled_alert_title">Receipts are disabled</string> - <string name="settings_section_title_delivery_receipts">SEND DELIVERY RECEIPTS TO</string> - <string name="sending_delivery_receipts_will_be_enabled">Sending delivery receipts will be enabled for all contacts.</string> - <string name="send_receipts_disabled_alert_msg">This group has over %1$d members, delivery receipts are not sent.</string> - <string name="error_enabling_delivery_receipts">Error enabling delivery receipts!</string> - <string name="delivery_receipts_are_disabled">Delivery receipts are disabled!</string> + <string name="v5_2_message_delivery_receipts">メッセージの配送通知</string> + <string name="delivery_receipts_title">配信通知!</string> + <string name="sending_delivery_receipts_will_be_enabled_all_profiles">配信通知の送信はすべてのチャットプロフィールのすべての連絡先に対して有効になります。</string> + <string name="message_delivery_error_title">メッセージ配信でエラー発生</string> + <string name="send_receipts_disabled_alert_title">通知は無効になりました</string> + <string name="settings_section_title_delivery_receipts">配信通知の送信</string> + <string name="sending_delivery_receipts_will_be_enabled">すべての連絡先で配信通知の送信が有効になります。</string> + <string name="send_receipts_disabled_alert_msg">このグループには %1$d 人以上のメンバーがいるため、配信通知は送信されません。</string> + <string name="error_enabling_delivery_receipts">配信通知を有効化する際にエラー発生!</string> + <string name="delivery_receipts_are_disabled">配信通知は無効になりました!</string> <string name="database_will_be_encrypted_and_passphrase_stored_in_settings">データベースは暗号化され、パスフレーズは設定に保存されます。</string> <string name="you_can_change_it_later">ランダムなパスフレーズは設定に平文として保存されます。 \n後で変更できます。</string> @@ -1399,4 +1393,206 @@ <string name="v5_3_simpler_incognito_mode_descr">接続時にシークレットモードを切り替えます。</string> <string name="member_contact_send_direct_message">ダイレクトメッセージを送る</string> <string name="rcv_group_event_member_created_contact">直接接続中</string> + <string name="rcv_direct_event_contact_deleted">削除済の連絡先</string> + <string name="v5_4_incognito_groups_descr">ランダムなプロフィールを使用してグループを作成します。</string> + <string name="create_group_button">グループの作成</string> + <string name="create_another_profile_button">プロフィールの作成</string> + <string name="connected_desktop">デスクトップに接続済</string> + <string name="multicast_connect_automatically">自動的に接続</string> + <string name="desktop_address">デスクトップアドレス</string> + <string name="camera_not_available">カメラが見つかりません</string> + <string name="discover_on_network">ローカルネットワーク上で検出</string> + <string name="connect_plan_connect_via_link">リンクで接続?</string> + <string name="connect_plan_connect_to_yourself">自分自身と接続?</string> + <string name="desktop_device">デスクトップ</string> + <string name="connected_to_desktop">デスクトップに接続済</string> + <string name="connecting_to_desktop">デスクトップに接続中</string> + <string name="desktop_devices">デスクトップ機器</string> + <string name="delete_messages__question">%d件のメッセージを削除?</string> + <string name="connect_with_contact_name_question">%1$sと接続?</string> + <string name="blocked_items_description">%d件のメッセージをブロック</string> + <string name="connected_mobile">モバイルに接続済</string> + <string name="create_chat_profile">チャットプロフィールの作成</string> + <string name="delete_and_notify_contact">削除と連絡先への通知</string> + <string name="desktop_connection_terminated">接続停止</string> + <string name="connect_to_desktop">デスクトップに接続</string> + <string name="disconnect_remote_hosts">モバイルの接続解除</string> + <string name="disconnect_remote_host">接続解除</string> + <string name="creating_link">リンクの作成中…</string> + <string name="rcv_group_events_count">%d件のグループイベント</string> + <string name="connected_to_mobile">モバイルに接続済</string> + <string name="devices">デバイス</string> + <string name="multicast_discoverable_via_local_network">ローカルネットワーク上で検出可能</string> + <string name="add_contact_tab">連絡先に追加</string> + <string name="disconnect_desktop_question">デスクトップの接続解除?</string> + <string name="desktop_app_version_is_incompatible">デスクトップ版アプリ%sはこのアプリと互換性がありません。</string> + <string name="encryption_renegotiation_error">暗号化再接続エラー</string> + <string name="error_alert_title">エラー</string> + <string name="marked_deleted_items_description">%d件のメッセージを削除</string> + <string name="moderated_items_description">%2$sにより%1$d件のメッセージを検閲</string> + <string name="disable_sending_recent_history">新規メンバーに履歴を送信しません。</string> + <string name="error_showing_content">コンテンツ表示エラー</string> + <string name="alert_text_encryption_renegotiation_failed">暗号化再接続に失敗しました。</string> + <string name="enable_camera_access">カメラを有効化</string> + <string name="error_sending_message_contact_invitation">招待状の送信エラー</string> + <string name="enter_this_device_name">このデバイスの名前を入力…</string> + <string name="error">エラー</string> + <string name="expand_verb">展開</string> + <string name="connect_plan_join_your_group">グループに参加?</string> + <string name="connect_plan_group_already_exists">グループはすでに存在します!</string> + <string name="recent_history_is_not_sent_to_new_members">過去の会話は新規メンバーに送信されません。</string> + <string name="desktop_incompatible_version">非互換バージョン</string> + <string name="new_desktop"><![CDATA[<i>(新規)</i>]]></string> + <string name="v5_4_incognito_groups">匿名グループ</string> + <string name="v5_4_better_groups_descr">より高速な参加と、より信頼性の高いメッセージ。</string> + <string name="found_desktop">デスクトップの検出</string> + <string name="error_showing_message">メッセージ表示エラー</string> + <string name="link_a_mobile">モバイルにリンク</string> + <string name="keep_unused_invitation_question">未使用の招待状を保持?</string> + <string name="invalid_name">不正な名前!</string> + <string name="invalid_qr_code">不正なQRコード</string> + <string name="non_content_uri_alert_title">不正なファイルパス</string> + <string name="keep_invitation_link">保持</string> + <string name="v5_4_link_mobile_desktop">モバイルとデスクトップのアプリを接続!</string> + <string name="linked_desktop_options">接続済のデスクトップのオプション</string> + <string name="linked_desktops">接続済のデスクトップ</string> + <string name="linked_mobiles">接続済のモバイル</string> + <string name="loading_remote_file_title">ファイルの読み込み中</string> + <string name="loading_chats">チャットの読み込み中…</string> + <string name="v5_4_block_group_members">ブロックしたグループメンバー</string> + <string name="connect_plan_repeat_connection_request">接続要求を繰り返しますか?</string> + <string name="connect_plan_you_are_already_connecting_to_vName"><![CDATA[すでに<b>%1$s</b>に接続しています。]]></string> + <string name="connect_plan_you_are_already_joining_the_group_via_this_link">あなたはすでにこのリンクでグループに参加しています。</string> + <string name="refresh_qr_code">再読み込み</string> + <string name="group_members_2">%sと%s</string> + <string name="new_mobile_device">新規モバイルデバイス</string> + <string name="only_one_device_can_work_at_the_same_time">同時に動作するのはひとつのデバイスだけです。</string> + <string name="you_can_make_address_visible_via_settings">設定でSimpleXの連絡先に表示させることができます。</string> + <string name="connect_plan_you_are_already_joining_the_group_vName"><![CDATA[あなたはすでにグループ<b>%1$s</b>に参加しています。]]></string> + <string name="connect_plan_this_is_your_own_one_time_link">これはあなた自身のワンタイムリンクです!</string> + <string name="chat_is_stopped_you_should_transfer_database">チャットが停止しています。このデータベースを他のデバイスで既に使用している場合は、チャットを開始する前に転送し直してください。</string> + <string name="v5_4_link_mobile_desktop_descr">セキュアな量子耐性プロトコル。</string> + <string name="open_on_mobile_and_scan_qr_code"><![CDATA[モバイルアプリで<i>デスクトップから使用</i>を開いてQRコードをスキャンします。]]></string> + <string name="connect_plan_already_connecting">すでに接続しています!</string> + <string name="retry_verb">再試行</string> + <string name="v5_4_block_group_members_descr">不要なメッセージを隠す。</string> + <string name="unlink_desktop_question">デスクトップのリンクを解除?</string> + <string name="v5_4_better_groups">改善されたグループ機能</string> + <string name="video_decoding_exception_desc">ビデオがデコードできません。別のビデオを試すか、開発者に連絡してください。</string> + <string name="rcv_group_event_1_member_connected">%sは接続済</string> + <string name="random_port">ランダム</string> + <string name="rcv_group_and_other_events">および %d件のその他イベント</string> + <string name="connect_plan_already_joining_the_group">すでにグループに参加しています!</string> + <string name="group_members_n">%sや%sなど%d人のメンバー</string> + <string name="this_device">このデバイス</string> + <string name="enable_sending_recent_history">新規メンバーに最大100通のメッセージ履歴を送信する。</string> + <string name="unblock_member_button">ブロックしていないメンバー</string> + <string name="remote_host_was_disconnected_toast"><![CDATA[モバイル<b>%s</b>が切断されました]]></string> + <string name="waiting_for_desktop">デスクトップを待機中…</string> + <string name="add_contact_button_to_create_link_or_connect_via_link"><![CDATA[<b>コンタクトの追加</b>: 新しい招待リンクを作成するか、受け取ったリンクから接続します。]]></string> + <string name="or_show_this_qr_code">またはこのコードを見せる</string> + <string name="recent_history_is_sent_to_new_members">新規メンバーには最大100通のメッセージ履歴が送信されます。</string> + <string name="code_you_scanned_is_not_simplex_link_qr_code">読み取ったコードはSimpleXのリンクQRコードではありません。</string> + <string name="contact_tap_to_connect">タップして接続</string> + <string name="this_device_name">このデバイス名</string> + <string name="the_text_you_pasted_is_not_a_link">あなたがペーストしたテキストはSimpleXのリンクではありません。</string> + <string name="connect_plan_you_are_already_in_group_vName"><![CDATA[あなたはすでにグループ<b>%1$s</b>に参加しています。]]></string> + <string name="connect_plan_this_is_your_own_simplex_address">これはあなた自身のSimpleXアドレスです!</string> + <string name="correct_name_to">正しい名前は%s?</string> + <string name="not_compatible">非互換です!</string> + <string name="waiting_for_mobile_to_connect">モバイルの接続を待機中:</string> + <string name="you_can_view_invitation_link_again">招待リンクは接続の詳細設定画面で再表示できます。</string> + <string name="remove_member_button">メンバーの削除</string> + <string name="start_chat_question">チャットを開始?</string> + <string name="block_member_confirmation">ブロック</string> + <string name="share_this_1_time_link">このワンタイム招待コードを共有する</string> + <string name="unblock_member_question">メンバーのブロックを解除?</string> + <string name="create_group_button_to_create_new_group"><![CDATA[<b>グループ作成</b>:新しいグループを作成する。]]></string> + <string name="open_port_in_firewall_desc">モバイルアプリからデスクトップへの接続を許可するには、ファイアウォールでこのポートを開いてください。</string> + <string name="block_member_button">ブロックしたメンバー</string> + <string name="recent_history">表示可能な履歴</string> + <string name="settings_section_title_use_from_desktop">デスクトップから使用</string> + <string name="session_code">セッションコード</string> + <string name="connect_plan_repeat_join_request">参加要求を繰り返しますか?</string> + <string name="button_remove_member_question">メンバーを削除?</string> + <string name="app_was_crashed">クラッシュしました</string> + <string name="la_app_passcode">アプリのパスコード</string> + <string name="connect_plan_you_are_already_connecting_via_this_one_time_link">あなたはすでにこのワンタイムリンクで接続しています!</string> + <string name="connect_plan_open_group">公開グループ</string> + <string name="this_device_version"><![CDATA[<i>(このデバイスv%s)</i>]]></string> + <string name="unlink_desktop">リンク解除</string> + <string name="new_chat">新規チャット</string> + <string name="unblock_member_desc">%sからのメッセージが表示されます!</string> + <string name="this_device_name_shared_with_mobile">デバイス名は接続されたモバイルクライアントと共有されます。</string> + <string name="verify_code_on_mobile">モバイルでコードを検証</string> + <string name="open_port_in_firewall_title">ファイヤーウォールのポートを開ける</string> + <string name="non_content_uri_alert_text">無効なファイルパスを共有しました。アプリ開発者に問題を報告してください。</string> + <string name="block_member_question">メンバーをブロック?</string> + <string name="group_member_role_author">作成者</string> + <string name="periodic_notifications_desc">アプリは定期的に新しいメッセージを取得します - 1日に数パーセントのバッテリーを使用します。このアプリはプッシュ通知を使用しません - あなたのデバイスからのデータはサーバーに送信されません。</string> + <string name="bad_desktop_address">不正なデスクトップアドレス</string> + <string name="or_scan_qr_code">またはQRコードでスキャンする</string> + <string name="paste_desktop_address">デスクトップアドレスを貼り付ける</string> + <string name="connect_plan_this_is_your_link_for_group_vName"><![CDATA[これはグループ<b>%1$s</b>のリンクです!]]></string> + <string name="verify_code_with_desktop">デスクトップでコードを検証</string> + <string name="scan_qr_code_from_desktop">デスクトップからQRコードをスキャン</string> + <string name="unblock_member_confirmation">ブロック解除</string> + <string name="to_preserve_privacy_simplex_has_background_service_instead_of_push_notifications_it_uses_a_few_pc_battery"><![CDATA[プライバシーを守るためアプリはプッシュ通知の代わりに<b>SimpleXバックグラウンドサービス</b>を備えています。- この機能は1日に数パーセントのバッテリーを消費します。]]></string> + <string name="v5_4_more_things_descr">- オプションで削除された連絡先を通知します。 +\n- プロフィール名に空白を含めることが可能になりました。 +\n- その他にも!</string> + <string name="v5_3_discover_join_groups_descr">- ディレクトリサービスに接続(ベータ)! +\n- 配信通知(最大20名)。 +\n- より速くより安定しました。</string> + <string name="tap_to_scan">タップしてスキャン</string> + <string name="connect_plan_you_have_already_requested_connection_via_this_address">このアドレスでの接続はすでに要求済です!</string> + <string name="terminal_always_visible">新規ウィンドウでコンソールを表示</string> + <string name="scan_from_mobile">モバイルからスキャン</string> + <string name="verify_connections">接続を確認</string> + <string name="tap_to_paste_link">タップしてリンクをペースト</string> + <string name="loading_remote_file_desc">リンク先のモバイルからファイルを読み込んでいますので、しばらくお待ちください。</string> + <string name="block_member_desc">%s からの新しいメッセージはすべて非表示になります!</string> + <string name="verify_connection">接続を確認</string> + <string name="no_connected_mobile">未接続のモバイル</string> + <string name="search_or_paste_simplex_link">検索またはSimpleXリンクをペースト</string> + <string name="blocked_item_description">ブロック済</string> + <string name="agent_internal_error_title">内部エラー</string> + <string name="agent_critical_error_title">重大エラー</string> + <string name="failed_to_create_user_invalid_title">表示名が無効です!</string> + <string name="remote_host_was_disconnected_title">切断されました。</string> + <string name="remote_ctrl_was_disconnected_title">切断されました。</string> + <string name="remote_host_disconnected_from"><![CDATA[携帯 <b>%s</b> が次の理由で切断されました: %s]]></string> + <string name="remote_ctrl_disconnected_with_reason">次の理由で切断されました: %s</string> + <string name="remote_ctrl_error_bad_state">PC版との接続が不安定</string> + <string name="remote_host_error_bad_state"><![CDATA[携帯 <b>%s</b> との接続が不安定]]></string> + <string name="remote_ctrl_error_inactive">PC版が非アクティブ</string> + <string name="remote_host_error_bad_version"><![CDATA[携帯版 <b>%s</b> のバージョンがサポートされてません。。両端末のバージョンが同じかどうか、ご確認ください。]]></string> + <string name="remote_ctrl_error_bad_invitation">PC版の招待コードが正しくない</string> + <string name="remote_ctrl_error_busy">PC版が処理中</string> + <string name="remote_ctrl_error_disconnected">PC版が切断されました</string> + <string name="remote_ctrl_error_bad_version">ご利用のPC版のバージョンがサポートされてません。両端末が同じバージョンかどうか、ご確認ください。</string> + <string name="possible_deadlock_title">デッドロック状態</string> + <string name="developer_options_section">開発者向けの設定</string> + <string name="possible_deadlock_desc">処理時間が異常にかかるようです: %1$d 秒。アプリが固まった恐れがあります: %2$s</string> + <string name="remote_host_error_busy"><![CDATA[携帯版 <b>%s</b> がただいま処理中]]></string> + <string name="possible_slow_function_desc">機能の処理時間が以上にかかってます: %1$d 秒: %2$s</string> + <string name="show_internal_errors">内部エラーを表示</string> + <string name="agent_internal_error_desc">開発側にお伝えください: +\n%s</string> + <string name="agent_critical_error_desc">開発側にお伝えください: +\n%s +\n +\nアプリを再起動してください。</string> + <string name="failed_to_create_user_invalid_desc">表示名が無効です。別の名前にしてください。</string> + <string name="remote_host_error_inactive"><![CDATA[携帯版 <b>%s</b> が非アクティブ]]></string> + <string name="remote_host_error_missing"><![CDATA[携帯版 <b>%s</b> が見つかりません]]></string> + <string name="remote_host_error_timeout"><![CDATA[携帯版に接続する段階で時間切れになりました <b>%s</b>]]></string> + <string name="remote_ctrl_error_timeout">PC版に接続する段階で時間切れになりました</string> + <string name="restart_chat_button">チャットを再起動</string> + <string name="remote_host_error_disconnected"><![CDATA[携帯版 <b>%s</b> が切断されました]]></string> + <string name="group_member_status_unknown_short">不明</string> + <string name="past_member_vName">過去のメンバー %1$s</string> + <string name="possible_slow_function_title">遅延が発生した機能</string> + <string name="show_slow_api_calls">遅いAPIコールを表示</string> + <string name="group_member_status_unknown">ステータス不明</string> </resources> \ No newline at end of file diff --git a/apps/multiplatform/common/src/commonMain/resources/MR/ko/strings.xml b/apps/multiplatform/common/src/commonMain/resources/MR/ko/strings.xml index 3c7554c972..af3972035f 100644 --- a/apps/multiplatform/common/src/commonMain/resources/MR/ko/strings.xml +++ b/apps/multiplatform/common/src/commonMain/resources/MR/ko/strings.xml @@ -27,7 +27,6 @@ <string name="icon_descr_context">컨텍스트 아이콘</string> <string name="icon_descr_server_status_connected">연결됨</string> <string name="back">뒤로</string> - <string name="add_new_contact_to_create_one_time_QR_code"><![CDATA[<b>새 대화 상대 추가</b> : 대화를 위한 일회용 QR 코드 만들기]]></string> <string name="cancel_verb">취소</string> <string name="icon_descr_cancel_live_message">라이브 메시지 취소</string> <string name="choose_file">파일 선택</string> @@ -112,7 +111,6 @@ <string name="change_member_role_question">그룹 역할을 바꾸시겠습니까\?</string> <string name="info_row_connection">연결</string> <string name="users_add">프로필 추가</string> - <string name="cant_delete_user_profile">사용자 프로필을 삭제할 수 없습니다!</string> <string name="chat_preferences_always">항상</string> <string name="chat_preferences_contact_allows">대화 상대가 허용함</string> <string name="contact_preferences">연락처 개별 설정</string> @@ -171,7 +169,6 @@ <string name="onboarding_notifications_mode_off_desc"><![CDATA[<b>배터리에 가장 좋음</b>. 앱이 실행 중일 때만 알림을 받게 됩니다 (백그라운드에서 실행되지 않음).]]></string> <string name="it_can_disabled_via_settings_notifications_still_shown"><![CDATA[<b>설정을 통해 비활성화할 수 있습니다.</b> – 앱이 실행되는 동안 알림이 표시됩니다.]]></string> <string name="both_you_and_your_contact_can_send_disappearing">당신과 대화 상대 모두 사라지는 메시지를 보낼 수 있습니다.</string> - <string name="scan_QR_code_to_connect_to_contact_who_shows_QR_code"><![CDATA[<b>QR 코드 스캔</b>: QR 코드를 보여주는 사람과 대화할 수 있습니다.]]></string> <string name="cannot_access_keychain">데이터베이스 암호를 저장하고 있는 Keystore에 접근할 수 없습니다.</string> <string name="onboarding_notifications_mode_service_desc"><![CDATA[<b>배터리 더욱 사용</b>! 백그라운드 서비스가 항상 실행됩니다. - 메시지를 수신되는 즉시 알림이 표시됩니다.]]></string> <string name="callstatus_ended">통화 종료됨 %1$s</string> @@ -202,7 +199,6 @@ <string name="status_contact_has_e2e_encryption">대화 상대와 종단간 암호화됨</string> <string name="alert_title_contact_connection_pending">대화 상대와 아직 연결되지 않았습니다!</string> <string name="archive_created_on_ts">%1$s에 생성 완료</string> - <string name="create_one_time_link">일회용 초대 링크 생성</string> <string name="create_secret_group_title">비밀 그룹 생성</string> <string name="accept_contact_incognito_button">익명 수락</string> <string name="chat_item_ttl_month">1개월</string> @@ -829,12 +825,10 @@ <string name="stop_chat_confirmation">멈추기</string> <string name="snd_group_event_changed_member_role">%s의 역할을 %s로 변경했어요.</string> <string name="section_title_for_console">콘솔용</string> - <string name="should_be_at_least_one_visible_profile">적어도 하나의 숨겨지지 않은 사용자 프로필이 있어야 해요.</string> <string name="set_group_preferences">그룹 설정 지정하기</string> <string name="snd_conn_event_switch_queue_phase_completed_for_member">%s의 주소를 바꿨어요</string> <string name="snd_conn_event_switch_queue_phase_completed">주소를 바꿨어요</string> <string name="snd_group_event_group_profile_updated">그룹 프로필 업데이트됨</string> - <string name="should_be_at_least_one_profile">적어도 하나의 사용자 프로필이 있어야 해요.</string> <string name="smp_servers_test_server">서버 테스트하기</string> <string name="smp_servers_use_server">서버 사용하기</string> <string name="smp_servers_use_server_for_new_conn">새로운 대화에 사용</string> diff --git a/apps/multiplatform/common/src/commonMain/resources/MR/lt/strings.xml b/apps/multiplatform/common/src/commonMain/resources/MR/lt/strings.xml index 163645c7d5..a8d6af6d40 100644 --- a/apps/multiplatform/common/src/commonMain/resources/MR/lt/strings.xml +++ b/apps/multiplatform/common/src/commonMain/resources/MR/lt/strings.xml @@ -117,7 +117,6 @@ <string name="image_descr_qr_code">QR kodas</string> <string name="icon_descr_help">pagalba</string> <string name="icon_descr_email">El. paštas</string> - <string name="create_one_time_link">Sukurti vienkartinio pakvietimo nuorodą</string> <string name="scan_code">Skenuoti kodą</string> <string name="database_passphrase_and_export">Duomenų bazės slaptafrazė ir eksportavimas</string> <string name="smp_servers_delete_server">Ištrinti serverį</string> @@ -364,7 +363,7 @@ <string name="disappearing_prohibited_in_this_chat">Išnykstančios žinutės šiame pokalbyje yra uždraustos.</string> <string name="voice_messages_are_prohibited">Balso žinutės šioje grupėje yra uždraustos.</string> <string name="connect_via_group_link">Prisijungti per grupės nuorodą\?</string> - <string name="connect_via_contact_link">Prisijungti per adresato nuorodą\?</string> + <string name="connect_via_contact_link">Prisijungti per adresato adresą?</string> <string name="sending_files_not_yet_supported">failų siuntimas kol kas nepalaikomas</string> <string name="invalid_message_format">neteisingas žinutės formatas</string> <string name="receiving_files_not_yet_supported">failų gavimas kol kas nepalaikomas</string> @@ -387,8 +386,6 @@ <string name="error_smp_test_certificate">Gali būti, kad liudijimo kontrolinis kodas serverio adrese yra neteisingas</string> <string name="smp_server_test_delete_file">Ištrinti failą</string> <string name="image_decoding_exception_title">Dekodavimo klaida</string> - <string name="add_new_contact_to_create_one_time_QR_code"><![CDATA[<b>Pridėti naują adresatą</b>: norėdami sukurti adresatui vienkartinį QR kodą.]]></string> - <string name="scan_QR_code_to_connect_to_contact_who_shows_QR_code"><![CDATA[<b>Skenuoti QR kodą</b>: norėdami prisijungti prie adresato, kuris jums rodo QR kodą.]]></string> <string name="clear_chat_button">Išvalyti pokalbį</string> <string name="unmute_chat">Įjungti pranešimus</string> <string name="invalid_QR_code">Neteisingas QR kodas</string> @@ -450,8 +447,6 @@ <string name="group_members_can_send_dms">Grupės nariai gali siųsti tiesiogines žinutes.</string> <string name="group_members_can_send_disappearing">Grupės nariai gali siųsti išnykstančias žinutes.</string> <string name="v4_3_improved_privacy_and_security_desc">Slėpti programėlės ekraną paskiausių programėlių sąraše.</string> - <string name="should_be_at_least_one_profile">Turėtų būti bent vienas naudotojo profilis.</string> - <string name="should_be_at_least_one_visible_profile">Turėtų būti matomas bent vienas naudotojo profilis.</string> <string name="chat_preferences_contact_allows">Adresatas leidžia</string> <string name="voice_prohibited_in_this_chat">Balso žinutės šiame pokalbyje yra uždraustos.</string> <string name="v4_4_disappearing_messages_desc">Išsiųstos žinutės bus ištrintos po nustatyto laiko.</string> @@ -472,7 +467,6 @@ <string name="join_group_button">Prisijungti</string> <string name="change_verb">Keisti</string> <string name="conn_stats_section_title_servers">SERVERIAI</string> - <string name="cant_delete_user_profile">Nepavyksta ištrinti naudotojo profilio!</string> <string name="clear_chat_menu_action">Išvalyti</string> <string name="unhide_profile">Nebeslėpti profilio</string> <string name="videos_limit_title">Per daug vaizdo įrašų!</string> @@ -616,4 +610,60 @@ <string name="cannot_access_keychain">Negalima pasiekti \"Keystore\", kad išsaugotumėte duomenų bazės slaptažodį</string> <string name="icon_descr_cancel_file_preview">Atšaukti failo peržiūrą</string> <string name="icon_descr_cancel_image_preview">Atšaukti vaizdo peržiūrą</string> + <string name="share_text_database_id">Duomenų bazės ID: %d</string> + <string name="delete_and_notify_contact">Ištrinti ir pranešti adresatui</string> + <string name="send_disappearing_message_custom_time">Tinkintas laikas</string> + <string name="v5_3_new_interface_languages_descr">Arabų, bulgarų, suomių, hebrajų, tajų ir ukrainiečių – dėkojame naudotojams ir Weblate.</string> + <string name="v5_3_new_interface_languages">6 naujos naudotojo sąsajos kalbos</string> + <string name="v5_1_custom_themes">Tinkinti apipavidalinimai</string> + <string name="multicast_connect_automatically">Prisijungti automatiškai</string> + <string name="chat_database_imported">Pokalbio duomenų bazė importuota</string> + <string name="connect_via_invitation_link">Prisijungti per vienkartinę nuorodą?</string> + <string name="icon_descr_close_button">Užvėrimo mygtukas</string> + <string name="devices">Įrenginiai</string> + <string name="connection_error_auth">Ryšio klaida (AUTH)</string> + <string name="disable_notifications_button">Išjungti pranešimus</string> + <string name="continue_to_next_step">Tęsti</string> + <string name="chat_database_deleted">Pokalbio duomenų bazė ištrinta</string> + <string name="choose_file_title">Pasirinkti failą</string> + <string name="contribute">Talkinti</string> + <string name="receipts_section_contacts">Adresatai</string> + <string name="settings_developer_tools">Plėtotojo įrankiai</string> + <string name="clear_note_folder_warning">Visos žinutės bus ištrintos – to neįmanoma bus atšaukti!</string> + <string name="add_contact_button_to_create_link_or_connect_via_link"><![CDATA[<b>Pridėti adresatą</b>: sukurti naują pakvietimo nuorodą arba prisijungti per gautą nuorodą.]]></string> + <string name="camera_not_available">Kamera neprieinama</string> + <string name="contacts_can_mark_messages_for_deletion">Adresatai gali žymėti žinutes ištrynimui; jūs galėsite jas peržiūrėti.</string> + <string name="create_another_profile_button">Sukurti profilį</string> + <string name="creating_link">Kuriama nuoroda…</string> + <string name="deleted_description">ištrinta</string> + <string name="delivery_receipts_are_disabled">Pranešimai apie pristatymą yra išjungti!</string> + <string name="turn_off_battery_optimization_button">Leisti</string> + <string name="in_developing_title">Jau greitai!</string> + <string name="developer_options_section">Plėtotojo parinktys</string> + <string name="colored_text">spalvotas</string> + <string name="connect_plan_already_joining_the_group">Jau prisijungiama prie grupės!</string> + <string name="connect_plan_connect_via_link">Prisijungti per nuorodą?</string> + <string name="create_simplex_address">Sukurti SimpleX adresą</string> + <string name="ttl_h">%dval.</string> + <string name="agent_critical_error_title">Kritinė klaida</string> + <string name="create_group_button_to_create_new_group"><![CDATA[<b>Sukurti grupę</b>: sukurti naują grupę.]]></string> + <string name="add_contact_tab">Pridėti adresatą</string> + <string name="customize_theme_title">Tinkinti apipavidalinimą</string> + <string name="chat_database_section">POKALBIO DUOMENŲ BAZĖ</string> + <string name="v4_6_chinese_spanish_interface">Naudotojo sąsaja kinų ir ispanų kalbomis</string> + <string name="delivery_receipts_title">Pranešimai apie pristatymą!</string> + <string name="auth_disable_simplex_lock">Išjungti SimpleX užraktą</string> + <string name="delivery">Pristatymas</string> + <string name="change_lock_mode">Keisti užrakto veikseną</string> + <string name="ttl_d">%dd.</string> + <string name="disappearing_message">Išnykstanti žinutė</string> + <string name="receipts_contacts_title_disable">Išjungti pranešimus apie pristatymą?</string> + <string name="send_receipts_disabled">išjungta</string> + <string name="v5_4_better_groups">Geresnės grupės</string> + <string name="v5_4_incognito_groups_descr">Sukurti grupę naudojant atsitiktinį profilį.</string> + <string name="v5_3_encrypt_local_files_descr">Programėlė šifruoja naujus vietinius failus (išskyrus vaizdo įrašus).</string> + <string name="connect_plan_already_connecting">Jau jungiamasi!</string> + <string name="connect_via_member_address_alert_title">Prisijungti tiesiogiai?</string> + <string name="create_group_button">Sukurti grupę</string> + <string name="dark_theme">Tamsus apipavidalinimas</string> </resources> \ No newline at end of file diff --git a/apps/multiplatform/common/src/commonMain/resources/MR/nl/strings.xml b/apps/multiplatform/common/src/commonMain/resources/MR/nl/strings.xml index 5f45304aac..d31e465957 100644 --- a/apps/multiplatform/common/src/commonMain/resources/MR/nl/strings.xml +++ b/apps/multiplatform/common/src/commonMain/resources/MR/nl/strings.xml @@ -19,7 +19,7 @@ <string name="network_enable_socks_info">Toegang tot de servers via SOCKS proxy op poort %d\? De proxy moet worden gestart voordat u deze optie inschakelt.</string> <string name="alert_title_cant_invite_contacts">Kan geen contacten uitnodigen!</string> <string name="allow_direct_messages">Sta het verzenden van directe berichten naar leden toe.</string> - <string name="allow_to_delete_messages">Sta toe om verzonden berichten onomkeerbaar te verwijderen.</string> + <string name="allow_to_delete_messages">Sta toe om verzonden berichten onomkeerbaar te verwijderen. (24 uur)</string> <string name="allow_to_send_voice">Sta toe om spraak berichten te verzenden.</string> <string name="chat_is_running">Chat is actief</string> <string name="clear_chat_menu_action">Wissen</string> @@ -59,14 +59,13 @@ <string name="v4_2_auto_accept_contact_requests">Contact verzoeken automatisch accepteren</string> <string name="bold_text">vetgedrukt</string> <string name="attach">Bijvoegen</string> - <string name="allow_irreversible_message_deletion_only_if">Sta het onomkeerbaar verwijderen van berichten alleen toe als uw contact dit toestaat.</string> + <string name="allow_irreversible_message_deletion_only_if">Sta het onomkeerbaar verwijderen van berichten alleen toe als uw contact dit toestaat. (24 uur)</string> <string name="allow_to_send_disappearing">Sta toe om verdwijnende berichten te verzenden.</string> <string name="allow_your_contacts_to_send_voice_messages">Sta toe dat uw contacten spraak berichten verzenden.</string> <string name="all_your_contacts_will_remain_connected">Al uw contacten blijven verbonden.</string> <string name="allow_voice_messages_question">Spraak berichten toestaan\?</string> <string name="onboarding_notifications_mode_periodic_desc"><![CDATA[<b>Goed voor de batterij</b>. Achtergrondservice controleert berichten elke 10 minuten. Mogelijk mist u oproepen of dringende berichten.]]></string> <string name="integrity_msg_bad_hash">Onjuiste bericht hash</string> - <string name="scan_QR_code_to_connect_to_contact_who_shows_QR_code"><![CDATA[<b>Scan QR-code</b>: om verbinding te maken met uw contact die u de QR-code laat zien.]]></string> <string name="integrity_msg_bad_id">Onjuiste bericht-ID</string> <string name="call_already_ended">Oproep al beëindigd!</string> <string name="chat_item_ttl_month">1 maand</string> @@ -77,7 +76,7 @@ <string name="clear_chat_warning">Alle berichten worden verwijderd, dit kan niet ongedaan worden gemaakt! De berichten worden ALLEEN voor jou verwijderd.</string> <string name="allow_disappearing_messages_only_if">Sta verdwijnende berichten alleen toe als uw contact dit toestaat.</string> <string name="allow_voice_messages_only_if">Sta spraak berichten alleen toe als uw contact ze toestaat.</string> - <string name="allow_your_contacts_irreversibly_delete">Laat uw contacten verzonden berichten onomkeerbaar verwijderen.</string> + <string name="allow_your_contacts_irreversibly_delete">Laat uw contacten verzonden berichten onomkeerbaar verwijderen. (24 uur)</string> <string name="allow_your_contacts_to_send_disappearing_messages">Sta toe dat uw contacten verdwijnende berichten verzenden.</string> <string name="chat_preferences_always">altijd</string> <string name="icon_descr_audio_off">Geluid uit</string> @@ -94,12 +93,11 @@ <string name="network_session_mode_user_description"><![CDATA[Er wordt een aparte TCP-verbinding (en SOCKS-referentie) gebruikt <b> voor elk chat profiel dat je in de app hebt </b>.]]></string> <string name="audio_call_no_encryption">audio oproep (niet e2e versleuteld)</string> <string name="notifications_mode_service_desc">Achtergrondservice is altijd actief, meldingen worden weergegeven zodra de berichten beschikbaar zijn.</string> - <string name="add_new_contact_to_create_one_time_QR_code"><![CDATA[<b>Nieuw contact toevoegen</b>: om een eenmalige QR-code voor uw contact te maken.]]></string> <string name="icon_descr_call_ended">Oproep beëindigd</string> <string name="turning_off_service_and_periodic">Batterijoptimalisatie is actief, waardoor achtergrondservice en periodieke verzoeken om nieuwe berichten worden uitgeschakeld. Je kunt ze weer inschakelen via instellingen.</string> <string name="onboarding_notifications_mode_off_desc"><![CDATA[<b>Het beste voor de batterij</b>. U ontvangt alleen meldingen wanneer de app wordt uitgevoerd (GEEN achtergrondservice).]]></string> <string name="it_can_disabled_via_settings_notifications_still_shown"><![CDATA[<b>Het kan worden uitgeschakeld via instellingen</b>, meldingen worden nog steeds weergegeven terwijl de app actief is.]]></string> - <string name="both_you_and_your_contacts_can_delete">Zowel jij als je contact kunnen verzonden berichten onherroepelijk verwijderen.</string> + <string name="both_you_and_your_contacts_can_delete">Zowel u als uw contact kunnen verzonden berichten onomkeerbaar verwijderen. (24 uur)</string> <string name="both_you_and_your_contact_can_send_disappearing">Zowel jij als je contact kunnen verdwijnende berichten sturen.</string> <string name="both_you_and_your_contact_can_send_voice">Zowel jij als je contact kunnen spraak berichten verzenden.</string> <string name="impossible_to_recover_passphrase"><![CDATA[<b>Let op</b>: u kunt het wachtwoord NIET herstellen of wijzigen als u het kwijt raakt.]]></string> @@ -203,13 +201,12 @@ <string name="clear_verification">Verwijderd verificatie</string> <string name="connect_button">Verbind</string> <string name="connect_via_link">Maak verbinding via link</string> - <string name="create_one_time_link">Maak een eenmalige uitnodiging link</string> <string name="colored_text">gekleurd</string> <string name="callstatus_connecting">Oproep verbinden…</string> <string name="create_profile_button">Maak</string> <string name="create_profile">Maak een profiel aan</string> <string name="delete_address">Adres verwijderen</string> - <string name="always_use_relay">Verbinden via relais</string> + <string name="always_use_relay">Altijd relay gebruiken</string> <string name="status_contact_has_e2e_encryption">contact heeft e2e-codering</string> <string name="status_contact_has_no_e2e_encryption">contact heeft geen e2e versleuteling</string> <string name="set_password_to_export_desc">De database is versleuteld met een willekeurige wachtwoord. Wijzig dit voordat u exporteert.</string> @@ -347,7 +344,7 @@ <string name="feature_enabled">ingeschakeld</string> <string name="feature_enabled_for_contact">ingeschakeld voor contact</string> <string name="feature_enabled_for_you">voor u ingeschakeld</string> - <string name="group_members_can_delete">Groepsleden kunnen verzonden berichten onherroepelijk verwijderen.</string> + <string name="group_members_can_delete">Groepsleden kunnen verzonden berichten onomkeerbaar verwijderen. (24 uur)</string> <string name="group_members_can_send_dms">Groepsleden kunnen directe berichten sturen</string> <string name="group_members_can_send_voice">Groepsleden kunnen spraak berichten verzenden.</string> <string name="v4_5_transport_isolation_descr">Per chat profiel (standaard) of per verbinding (BETA).</string> @@ -551,7 +548,7 @@ <string name="smp_servers_preset_address">Vooraf ingesteld server adres</string> <string name="network_use_onion_hosts_no_desc_in_alert">Onion hosts worden niet gebruikt.</string> <string name="onboarding_notifications_mode_title">Privé meldingen</string> - <string name="paste_the_link_you_received">Plak de ontvangen link</string> + <string name="paste_the_link_you_received">Plak de link die je hebt ontvangen</string> <string name="onboarding_notifications_mode_periodic">Periodiek</string> <string name="open_verb">Open</string> <string name="open_simplex_chat_to_accept_call">Open SimpleX Chat om de oproep te accepteren</string> @@ -563,7 +560,7 @@ <string name="chat_preferences_on">aan</string> <string name="only_you_can_send_disappearing">Alleen jij kunt verdwijnende berichten verzenden.</string> <string name="only_your_contact_can_send_disappearing">Alleen uw contact kan verdwijnende berichten verzenden.</string> - <string name="only_you_can_delete_messages">Alleen jij kunt berichten onomkeerbaar verwijderen (je contact kan ze markeren voor verwijdering).</string> + <string name="only_you_can_delete_messages">Alleen u kunt berichten onomkeerbaar verwijderen (uw contact kan ze markeren voor verwijdering). (24 uur)</string> <string name="feature_offered_item_with_param">voorgesteld %s: %2s</string> <string name="old_database_archive">Oud database archief</string> <string name="enter_correct_current_passphrase">Voer het juiste huidige wachtwoord in.</string> @@ -591,7 +588,7 @@ <string name="network_use_onion_hosts_no_desc">Onion hosts worden niet gebruikt.</string> <string name="opensource_protocol_and_code_anybody_can_run_servers">Open-source protocol en code. Iedereen kan de servers draaien.</string> <string name="people_can_connect_only_via_links_you_share">Mensen kunnen alleen verbinding met u maken via de links die u deelt.</string> - <string name="only_your_contact_can_delete">Alleen uw contact kan berichten onherroepelijk verwijderen (u kunt ze markeren voor verwijdering).</string> + <string name="only_your_contact_can_delete">Alleen uw contact kan berichten onherroepelijk verwijderen (u kunt ze markeren voor verwijdering). (24 uur)</string> <string name="only_you_can_send_voice">Alleen jij kunt spraak berichten verzenden.</string> <string name="only_your_contact_can_send_voice">Alleen uw contact kan spraak berichten verzenden.</string> <string name="prohibit_message_deletion">Verbied het onomkeerbaar verwijderen van berichten.</string> @@ -680,7 +677,7 @@ <string name="you_invited_a_contact">Je hebt je contact uitgenodigd</string> <string name="alert_text_connection_pending_they_need_to_be_online_can_delete_and_retry">Uw contact moet online zijn om de verbinding te voltooien. \nU kunt deze verbinding verbreken en het contact verwijderen en later proberen met een nieuwe link.</string> - <string name="image_descr_qr_code">QR code</string> + <string name="image_descr_qr_code">QR-code</string> <string name="icon_descr_settings">Instellingen</string> <string name="contact_wants_to_connect_with_you">wil met je in contact komen!</string> <string name="icon_descr_address">SimpleX Adres</string> @@ -741,7 +738,7 @@ <string name="relay_server_if_necessary">Relay server wordt alleen gebruikt als dat nodig is. Een andere partij kan uw IP-adres zien.</string> <string name="your_ice_servers">Uw ICE servers</string> <string name="alert_title_skipped_messages">Overgeslagen berichten</string> - <string name="call_connection_via_relay">via relais</string> + <string name="call_connection_via_relay">via relay</string> <string name="icon_descr_video_off">Video uit</string> <string name="protect_app_screen">App scherm verbergen</string> <string name="your_privacy">Uw privacy</string> @@ -961,7 +958,6 @@ <string name="you_are_observer">jij bent waarnemer</string> <string name="language_system">Systeem</string> <string name="v4_6_audio_video_calls">Audio en video oproepen</string> - <string name="cant_delete_user_profile">Kan gebruikers profiel niet verwijderen!</string> <string name="confirm_password">Bevestig wachtwoord</string> <string name="v4_6_chinese_spanish_interface">Chinese en Spaanse interface</string> <string name="enter_password_to_show">Voer wachtwoord in bij zoeken</string> @@ -993,12 +989,10 @@ <string name="v4_6_audio_video_calls_descr">Ondersteuning voor bluetooth en andere verbeteringen.</string> <string name="tap_to_activate_profile">Tik om profiel te activeren.</string> <string name="v4_6_chinese_spanish_interface_descr">Dank aan de gebruikers – draag bij via Weblate!</string> - <string name="should_be_at_least_one_profile">Er moet ten minste één gebruikers profiel zijn.</string> <string name="you_can_hide_or_mute_user_profile">U kunt een gebruikers profiel verbergen of dempen - houd het vast voor het menu.</string> <string name="user_unhide">zichtbaar maken</string> <string name="user_unmute">Dempen opheffen</string> <string name="group_welcome_title">Welkomst bericht</string> - <string name="should_be_at_least_one_visible_profile">"Er moet ten minste één zichtbaar gebruikers profiel zijn."</string> <string name="to_reveal_profile_enter_password">Om uw verborgen profiel te onthullen, voert u een volledig wachtwoord in een zoekveld in op de pagina Uw chat profielen.</string> <string name="button_welcome_message">Welkomst bericht</string> <string name="you_will_still_receive_calls_and_ntfs">U ontvangt nog steeds oproepen en meldingen van gedempte profielen wanneer deze actief zijn.</string> @@ -1383,7 +1377,7 @@ <string name="open_database_folder">Database map openen</string> <string name="passphrase_will_be_saved_in_settings">Het wachtwoord wordt als platte tekst in de instellingen opgeslagen nadat u deze hebt gewijzigd of de app opnieuw hebt opgestart.</string> <string name="settings_is_storing_in_clear_text">Het wachtwoord wordt als leesbare tekst in de instellingen opgeslagen.</string> - <string name="socks_proxy_setting_limitations"><![CDATA[<b>Let op</b>: bericht en bestands relais zijn verbonden via SOCKS-proxy. Voor oproepen en het verzenden van link voorbeelden wordt gebruik gemaakt van een directe verbinding.]]></string> + <string name="socks_proxy_setting_limitations"><![CDATA[<b>Let op</b>: bericht en bestands relays zijn verbonden via SOCKS-proxy. Voor oproepen en het verzenden van link voorbeelden wordt gebruik gemaakt van een directe verbinding.]]></string> <string name="encrypt_local_files">Versleutel lokale bestanden</string> <string name="v5_3_encrypt_local_files">Versleutel opgeslagen bestanden en media</string> <string name="v5_3_new_desktop_app">Nieuwe desktop app!</string> @@ -1402,7 +1396,7 @@ <string name="compose_send_direct_message_to_connect">Stuur een direct bericht om verbinding te maken</string> <string name="member_contact_send_direct_message">stuur een direct bericht</string> <string name="rcv_group_event_member_created_contact">direct verbonden</string> - <string name="expand_verb">Uitbreiden</string> + <string name="expand_verb">Uitklappen</string> <string name="connect_plan_repeat_connection_request">Verbindingsverzoek herhalen?</string> <string name="rcv_direct_event_contact_deleted">verwijderd contact</string> <string name="error_alert_title">Fout</string> @@ -1419,7 +1413,7 @@ <string name="connect_plan_connect_via_link">Verbinden via link?</string> <string name="connect_plan_already_joining_the_group">Al lid van de groep!</string> <string name="group_members_n">%s, %s en %d leden</string> - <string name="moderated_items_description">%d berichten gemodereerd door %s</string> + <string name="moderated_items_description">%1$d berichten gemodereerd door %2$s</string> <string name="connect_plan_connect_to_yourself">Verbinding maken met jezelf?</string> <string name="contact_tap_to_connect">Tik om verbinding te maken</string> <string name="correct_name_to">Juiste naam voor %s?</string> @@ -1431,7 +1425,7 @@ <string name="block_member_button">Lid blokkeren</string> <string name="connect_plan_repeat_join_request">Deelnameverzoek herhalen?</string> <string name="button_remove_member_question">Lid verwijderen?</string> - <string name="delete_and_notify_contact">Contact verwijderen en op de hoogte stellen</string> + <string name="delete_and_notify_contact">Verwijderen en contact op de hoogte stellen</string> <string name="connect_plan_open_group">Open groep</string> <string name="unblock_member_desc">Berichten van %s worden getoond!</string> <string name="error_sending_message_contact_invitation">Fout bij verzenden van uitnodiging</string> @@ -1442,17 +1436,17 @@ <string name="terminal_always_visible">Console in nieuw venster weergeven</string> <string name="block_member_desc">Alle nieuwe berichten van %s worden verborgen!</string> <string name="blocked_item_description">geblokkeerd</string> - <string name="connect_plan_you_are_already_connecting_to_vName">Je bent al verbonden met %1$s.</string> + <string name="connect_plan_you_are_already_connecting_to_vName"><![CDATA[Je bent al verbonden met <b>%1$s</b>.]]></string> <string name="connect_plan_you_are_already_joining_the_group_via_this_link">Je wordt al lid van de groep via deze link.</string> - <string name="connect_plan_you_are_already_joining_the_group_vName">Je bent al lid van de groep %1$s.</string> + <string name="connect_plan_you_are_already_joining_the_group_vName"><![CDATA[Je bent al lid van de groep <b>%1$s</b>.]]></string> <string name="connect_plan_this_is_your_own_one_time_link">Dit is uw eigen eenmalige link!</string> <string name="unblock_member_button">Lid deblokkeren</string> - <string name="connect_plan_you_are_already_in_group_vName">Je zit al in groep %1$s.</string> + <string name="connect_plan_you_are_already_in_group_vName"><![CDATA[Je zit al in groep <b>%1$s</b>.]]></string> <string name="connect_plan_this_is_your_own_simplex_address">Dit is uw eigen SimpleX adres!</string> <string name="unblock_member_question">Lid deblokkeren?</string> <string name="connect_plan_you_are_already_connecting_via_this_one_time_link">Je maakt al verbinding via deze eenmalige link!</string> <string name="non_content_uri_alert_text">Je hebt een ongeldig bestandslocatie gedeeld. Rapporteer het probleem aan de app-ontwikkelaars.</string> - <string name="connect_plan_this_is_your_link_for_group_vName">Dit is jouw link voor groep %1$s!</string> + <string name="connect_plan_this_is_your_link_for_group_vName"><![CDATA[Dit is jouw link voor groep <b>%1$s</b>!]]></string> <string name="unblock_member_confirmation">Deblokkeren</string> <string name="connect_plan_you_have_already_requested_connection_via_this_address">U heeft al een verbinding aangevraagd via dit adres!</string> <string name="encryption_renegotiation_error">Fout bij heronderhandeling van codering</string> @@ -1520,4 +1514,120 @@ <string name="found_desktop">Desktop gevonden</string> <string name="not_compatible">Niet compatibel!</string> <string name="multicast_discoverable_via_local_network">Vindbaar via lokaal netwerk</string> + <string name="refresh_qr_code">Vernieuwen</string> + <string name="create_chat_profile">Chatprofiel aanmaken</string> + <string name="disconnect_remote_hosts">Mobiele telefoons loskoppelen</string> + <string name="no_connected_mobile">Geen verbonden mobiel</string> + <string name="random_port">willekeurig</string> + <string name="open_port_in_firewall_desc">Om een mobiele app verbinding te laten maken met de desktop, opent u deze poort in uw firewall, als u deze hebt ingeschakeld</string> + <string name="app_was_crashed">Weergave gecrasht</string> + <string name="open_port_in_firewall_title">Open poort in firewall</string> + <string name="error_showing_content">Fout bij het tonen van inhoud</string> + <string name="error_showing_message">fout bij weergeven bericht</string> + <string name="you_can_make_address_visible_via_settings">Je kunt het via Instellingen zichtbaar maken voor je SimpleX contacten.</string> + <string name="recent_history_is_not_sent_to_new_members">Geschiedenis wordt niet naar nieuwe leden gestuurd.</string> + <string name="retry_verb">Opnieuw proberen</string> + <string name="camera_not_available">Camera niet beschikbaar</string> + <string name="enable_sending_recent_history">Stuur tot 100 laatste berichten naar nieuwe leden.</string> + <string name="add_contact_button_to_create_link_or_connect_via_link"><![CDATA[<b>Contact toevoegen</b>: om een nieuwe uitnodigingslink te maken, of om verbinding te maken via een link die u heeft ontvangen.]]></string> + <string name="disable_sending_recent_history">Stuur geen geschiedenis naar nieuwe leden.</string> + <string name="or_show_this_qr_code">Of laat deze code zien</string> + <string name="recent_history_is_sent_to_new_members">Er worden maximaal 100 laatste berichten naar nieuwe leden verzonden.</string> + <string name="code_you_scanned_is_not_simplex_link_qr_code">De code die u heeft gescand is geen SimpleX link QR-code.</string> + <string name="the_text_you_pasted_is_not_a_link">De tekst die u hebt geplakt is geen SimpleX link.</string> + <string name="enable_camera_access">Schakel cameratoegang in</string> + <string name="you_can_view_invitation_link_again">U kunt de uitnodigingslink opnieuw bekijken in de verbindingsdetails.</string> + <string name="keep_unused_invitation_question">Ongebruikte uitnodiging bewaren?</string> + <string name="share_this_1_time_link">Deel deze eenmalige uitnodigingslink</string> + <string name="create_group_button_to_create_new_group"><![CDATA[<b>Groep aanmaken</b>: om een nieuwe groep aan te maken.]]></string> + <string name="recent_history">Zichtbare geschiedenis</string> + <string name="la_app_passcode">App toegangscode</string> + <string name="new_chat">Nieuw gesprek</string> + <string name="loading_chats">Gesprekken laden…</string> + <string name="creating_link">Link maken…</string> + <string name="or_scan_qr_code">Of scan de QR-code</string> + <string name="invalid_qr_code">Ongeldige QR-code</string> + <string name="add_contact_tab">Contact toevoegen</string> + <string name="tap_to_scan">Tik om te scannen</string> + <string name="keep_invitation_link">Bewaar</string> + <string name="tap_to_paste_link">Tik om de link te plakken</string> + <string name="search_or_paste_simplex_link">Zoek of plak een SimpleX link</string> + <string name="chat_is_stopped_you_should_transfer_database">De chat is gestopt. Als u deze database al op een ander apparaat heeft gebruikt, moet u deze terugzetten voordat u met chatten begint.</string> + <string name="start_chat_question">Begin chat?</string> + <string name="show_internal_errors">Toon interne fouten</string> + <string name="agent_critical_error_title">Kritische fout</string> + <string name="agent_internal_error_title">Interne fout</string> + <string name="agent_internal_error_desc">Rapporteer dit alstublieft aan de ontwikkelaars: +\n%s</string> + <string name="agent_critical_error_desc">Rapporteer dit alstublieft aan de ontwikkelaars: +\n%s +\n +\nHet wordt aanbevolen om de app opnieuw te starten.</string> + <string name="remote_ctrl_error_bad_version">Desktop heeft een niet-ondersteunde versie. Zorg ervoor dat u op beide apparaten dezelfde versie gebruikt</string> + <string name="failed_to_create_user_invalid_title">Ongeldige weergavenaam!</string> + <string name="failed_to_create_user_invalid_desc">Deze weergavenaam is ongeldig. Kies een andere naam.</string> + <string name="remote_host_was_disconnected_title">Verbinding gestopt</string> + <string name="remote_ctrl_was_disconnected_title">Verbinding gestopt</string> + <string name="remote_host_disconnected_from"><![CDATA[Verbinding met mobiel <b>%s</b> \u0020is verbroken met als reden: %s]]></string> + <string name="remote_host_error_busy"><![CDATA[Mobiel <b>%s</b> is bezet]]></string> + <string name="remote_host_error_inactive"><![CDATA[Mobiel <b>%s</b> is inactief]]></string> + <string name="remote_host_error_missing"><![CDATA[Mobiel <b>%s</b> ontbreekt]]></string> + <string name="remote_host_error_bad_state"><![CDATA[De verbinding met de mobiel <b>%s</b> is in slechte staat]]></string> + <string name="remote_ctrl_error_disconnected">De verbinding met desktop is verbroken</string> + <string name="possible_deadlock_title">Impasse</string> + <string name="possible_slow_function_desc">Uitvoering van functie duurt te lang: %1$d seconden: %2$s</string> + <string name="possible_slow_function_title">Langzame functie</string> + <string name="developer_options_section">Ontwikkelaars opties</string> + <string name="show_slow_api_calls">Toon langzame API aanroepen</string> + <string name="past_member_vName">Voormalig lid %1$s</string> + <string name="group_member_status_unknown_short">onbekend</string> + <string name="remote_ctrl_disconnected_with_reason">Verbinding verbroken met als reden: %s</string> + <string name="remote_ctrl_error_busy">Desktop is bezet</string> + <string name="remote_ctrl_error_inactive">Desktop is inactief</string> + <string name="remote_host_error_disconnected"><![CDATA[Mobiele verbinding <b>%s</b> is verbroken]]></string> + <string name="restart_chat_button">Chat opnieuw starten</string> + <string name="remote_host_error_timeout"><![CDATA[Time-out bereikt tijdens het verbinden met de mobiel <b>%s</b>]]></string> + <string name="remote_ctrl_error_bad_state">De verbinding met de desktop is in slechte staat</string> + <string name="possible_deadlock_desc">Het uitvoeren van de code duurt te lang: %1$d seconden. Waarschijnlijk is de app vastgelopen: %2$s</string> + <string name="remote_ctrl_error_bad_invitation">Desktop heeft verkeerde uitnodigingscode</string> + <string name="remote_host_error_bad_version"><![CDATA[Mobiel <b>%s</b> heeft een niet-ondersteunde versie. Zorg ervoor dat u op beide apparaten dezelfde versie gebruikt]]></string> + <string name="remote_ctrl_error_timeout">Time-out bereikt tijdens het verbinden met de desktop</string> + <string name="group_member_status_unknown">onbekende status</string> + <string name="v5_5_message_delivery">Verbeterde berichtbezorging</string> + <string name="v5_5_join_group_conversation">Neem deel aan groepsgesprekken</string> + <string name="v5_5_simpler_connect_ui">Plak een link om te verbinden!</string> + <string name="v5_5_private_notes">Privé notities</string> + <string name="clear_note_folder_warning">Alle berichten worden verwijderd. Dit kan niet ongedaan worden gemaakt!</string> + <string name="info_row_created_at">Gemaakt op</string> + <string name="error_creating_message">Fout bij het maken van een bericht</string> + <string name="v5_5_new_interface_languages">Hongaarse en Turkse gebruikersinterface</string> + <string name="v5_5_join_group_conversation_descr">Recente geschiedenis en verbeterde directory-bot.</string> + <string name="note_folder_local_display_name">Privé notities</string> + <string name="share_text_created_at">Gemaakt op: %s</string> + <string name="profile_update_event_member_name_changed">lid %1$s gewijzigd in %2$s</string> + <string name="profile_update_event_contact_name_changed">contactpersoon %1$s gewijzigd in %2$s</string> + <string name="error_deleting_note_folder">Fout bij verwijderen van privénotities</string> + <string name="clear_note_folder_question">Privénotities verwijderen?</string> + <string name="v5_5_simpler_connect_ui_descr">Zoekbalk accepteert uitnodigingslinks.</string> + <string name="v5_5_private_notes_descr">‐Met versleutelde bestanden en media.</string> + <string name="v5_5_message_delivery_descr">Met verminderd batterijgebruik.</string> + <string name="saved_message_title">Opgeslagen bericht</string> + <string name="profile_update_event_updated_profile">bijgewerkt profiel</string> + <string name="profile_update_event_removed_address">contactadres verwijderd</string> + <string name="profile_update_event_removed_picture">profielfoto verwijderd</string> + <string name="profile_update_event_set_new_address">nieuw contactadres instellen</string> + <string name="profile_update_event_set_new_picture">nieuwe profielfoto instellen</string> + <string name="member_blocked_by_admin">Geblokkeerd door beheerder</string> + <string name="block_for_all">Blokkeren voor iedereen</string> + <string name="block_for_all_question">Lid voor iedereen blokkeren?</string> + <string name="unblock_for_all">Deblokkeer voor iedereen</string> + <string name="member_info_member_blocked">geblokkeerd</string> + <string name="blocked_by_admin_item_description">geblokkeerd door beheerder</string> + <string name="rcv_group_event_member_blocked">%s geblokkeerd</string> + <string name="blocked_by_admin_items_description">%d berichten geblokkeerd door beheerder</string> + <string name="rcv_group_event_member_unblocked">%s gedeblokkeerd</string> + <string name="error_blocking_member_for_all">Fout bij blokkeren van lid voor iedereen</string> + <string name="unblock_for_all_question">Lid voor iedereen deblokkeren?</string> + <string name="snd_group_event_member_blocked">je hebt %s geblokkeerd</string> + <string name="snd_group_event_member_unblocked">je hebt %s gedeblokkeerd</string> </resources> \ No newline at end of file diff --git a/apps/multiplatform/common/src/commonMain/resources/MR/pl/strings.xml b/apps/multiplatform/common/src/commonMain/resources/MR/pl/strings.xml index e811e47ea1..a09b20f5ec 100644 --- a/apps/multiplatform/common/src/commonMain/resources/MR/pl/strings.xml +++ b/apps/multiplatform/common/src/commonMain/resources/MR/pl/strings.xml @@ -229,7 +229,6 @@ <string name="accept_contact_button">Akceptuj</string> <string name="accept_contact_incognito_button">Akceptuj incognito</string> <string name="clear_chat_warning">Wszystkie wiadomości zostaną usunięte - nie można tego cofnąć! Wiadomości zostaną usunięte TYLKO dla Ciebie.</string> - <string name="scan_QR_code_to_connect_to_contact_who_shows_QR_code"><![CDATA[<b>Zeskanuj kod QR</b>: aby połączyć się z kontaktem, który pokaże Ci kod QR.]]></string> <string name="icon_descr_cancel_link_preview">anuluj podgląd linku</string> <string name="clear_verb">Wyczyść</string> <string name="clear_chat_menu_action">Wyczyść</string> @@ -447,7 +446,7 @@ <string name="onboarding_notifications_mode_service_desc"><![CDATA[<b>Zużywa więcej baterii</b>! Usługa zawsze działa w tle - powiadomienia są wyświetlane, gdy tylko wiadomości są dostępne.]]></string> <string name="incoming_audio_call">Przychodzące połączenie audio</string> <string name="incoming_video_call">Przychodzące połączenie wideo</string> - <string name="paste_the_link_you_received">Wklej otrzymany link</string> + <string name="paste_the_link_you_received">Wklej link, który otrzymałeś</string> <string name="video_call_no_encryption">połączenie wideo (bez szyfrowania e2e)</string> <string name="accept">Akceptuj</string> <string name="encrypted_audio_call">zaszyfrowane e2e połączenie audio</string> @@ -744,7 +743,6 @@ <string name="group_is_decentralized">W pełni zdecentralizowana – widoczna tylko dla członków.</string> <string name="member_role_will_be_changed_with_invitation">Rola zostanie zmieniona na \"%s\". Członek otrzyma nowe zaproszenie.</string> <string name="group_welcome_title">Wiadomość powitalna</string> - <string name="cant_delete_user_profile">Nie można usunąć profilu użytkownika!</string> <string name="users_delete_question">Usunąć profil czatu\?</string> <string name="users_delete_profile_for">Usuń profil czatu dla</string> <string name="dont_show_again">Nie pokazuj ponownie</string> @@ -813,11 +811,11 @@ <string name="your_preferences">Twoje preferencje</string> <string name="incognito_random_profile">Twój losowy profil</string> <string name="allow_direct_messages">Zezwalaj na wysyłanie bezpośrednich wiadomości do członków.</string> - <string name="allow_to_delete_messages">Zezwól na nieodwracalne usunięcie wysłanych wiadomości.</string> + <string name="allow_to_delete_messages">Zezwól na nieodwracalne usunięcie wysłanych wiadomości. (24 godziny)</string> <string name="allow_to_send_voice">Zezwól na wysyłanie wiadomości głosowych.</string> <string name="allow_voice_messages_only_if">Zezwalaj na wiadomości głosowe tylko wtedy, gdy Twój kontakt na nie pozwala.</string> <string name="allow_your_contacts_to_send_voice_messages">Zezwól swoim kontaktom na wysyłanie wiadomości głosowych.</string> - <string name="both_you_and_your_contacts_can_delete">Zarówno Ty, jak i Twój kontakt możecie nieodwracalnie usunąć wysłane wiadomości.</string> + <string name="both_you_and_your_contacts_can_delete">Zarówno Ty, jak i Twój kontakt możecie nieodwracalnie usunąć wysłane wiadomości. (24 godziny)</string> <string name="both_you_and_your_contact_can_send_disappearing">Zarówno Ty, jak i Twój kontakt możecie wysyłać znikające wiadomości.</string> <string name="contacts_can_mark_messages_for_deletion">Kontakty mogą oznaczać wiadomości do usunięcia; będziesz mógł je zobaczyć.</string> <string name="delete_after">Usuń po</string> @@ -830,11 +828,11 @@ <string name="ttl_mth">%d mies</string> <string name="ttl_s">%ds</string> <string name="ttl_sec">%d sek</string> - <string name="group_members_can_delete">Członkowie grupy mogą nieodwracalnie usuwać wysłane wiadomości.</string> + <string name="group_members_can_delete">Członkowie grupy mogą nieodwracalnie usuwać wysłane wiadomości. (24 godziny)</string> <string name="group_members_can_send_dms">Członkowie grupy mogą wysyłać bezpośrednie wiadomości.</string> <string name="message_deletion_prohibited">Nieodwracalne usuwanie wiadomości jest na tym czacie zabronione.</string> <string name="message_deletion_prohibited_in_chat">Nieodwracalne usuwanie wiadomości jest w tej grupie zabronione.</string> - <string name="only_you_can_delete_messages">Tylko Ty możesz nieodwracalnie usunąć wiadomości (Twój kontakt może oznaczyć je do usunięcia).</string> + <string name="only_you_can_delete_messages">Tylko Ty możesz nieodwracalnie usunąć wiadomości (Twój kontakt może oznaczyć je do usunięcia). (24 godziny)</string> <string name="only_you_can_send_disappearing">Tylko Ty możesz wysyłać znikające wiadomości.</string> <string name="only_you_can_send_voice">Tylko Ty możesz wysyłać wiadomości głosowe.</string> <string name="only_your_contact_can_send_disappearing">Tylko Twój kontakt może wysyłać znikające wiadomości.</string> @@ -895,7 +893,7 @@ <string name="v4_6_audio_video_calls_descr">Obsługa bluetooth i inne ulepszenia.</string> <string name="v4_5_italian_interface_descr">Podziękowania dla użytkowników - wkład za pośrednictwem Weblate!</string> <string name="v4_6_chinese_spanish_interface_descr">Podziękowania dla użytkowników - wkład za pośrednictwem Weblate!</string> - <string name="allow_your_contacts_irreversibly_delete">Zezwól swoim kontaktom na nieodwracalne usuwanie wysłanych wiadomości.</string> + <string name="allow_your_contacts_irreversibly_delete">Zezwól swoim kontaktom na nieodwracalne usuwanie wysłanych wiadomości. (24 godziny)</string> <string name="about_simplex_chat">O SimpleX Chat</string> <string name="above_then_preposition_continuation">powyżej, wtedy:</string> <string name="accept_connection_request__question">Zaakceptować prośbę o połączenie\?</string> @@ -909,7 +907,7 @@ <string name="allow_verb">Pozwól</string> <string name="chat_preferences_always">zawsze</string> <string name="notifications_mode_service">Zawsze włączona</string> - <string name="allow_irreversible_message_deletion_only_if">Zezwalaj na nieodwracalne usuwanie wiadomości tylko wtedy, gdy Twój kontakt Ci na to pozwoli.</string> + <string name="allow_irreversible_message_deletion_only_if">Zezwalaj na nieodwracalne usuwanie wiadomości tylko wtedy, gdy Twój kontakt Ci na to pozwoli. (24 godziny)</string> <string name="allow_to_send_disappearing">Zezwól na wysyłanie znikających wiadomości.</string> <string name="allow_voice_messages_question">Zezwolić na wiadomości głosowe\?</string> <string name="notifications_mode_off_desc">Aplikacja może otrzymywać powiadomienia tylko wtedy, gdy jest uruchomiona, żadna usługa w tle nie zostanie uruchomiona</string> @@ -917,7 +915,6 @@ <string name="auth_unavailable">Uwierzytelnianie niedostępne</string> <string name="attach">Dołącz</string> <string name="back">Wstecz</string> - <string name="add_new_contact_to_create_one_time_QR_code"><![CDATA[<b>Dodaj nowy kontakt</b>: aby stworzyć swój jednorazowy kod QR dla kontaktu.]]></string> <string name="turning_off_service_and_periodic">Optymalizacja baterii jest aktywna, wyłącza usługi w tle i okresowe żądania nowych wiadomości. Możesz je ponownie włączyć za pośrednictwem ustawień.</string> <string name="it_can_disabled_via_settings_notifications_still_shown"><![CDATA[<b>Można je wyłączyć poprzez ustawienia</b> - powiadomienia nadal będą pokazywane podczas działania aplikacji.]]></string> <string name="onboarding_notifications_mode_off_desc"><![CDATA[<b>Najlepsze dla baterii</b>. Będziesz otrzymywać powiadomienia tylko wtedy, gdy aplikacja jest uruchomiona (NIE w tle).]]></string> @@ -933,7 +930,6 @@ <string name="connection_error_auth">Błąd połączenia (UWIERZYTELNIANIE)</string> <string name="connect_via_link_or_qr">Połącz się przez link / kod QR</string> <string name="archive_created_on_ts">Utworzony na %1$s</string> - <string name="create_one_time_link">Utwórz jednorazowy link do zaproszenia</string> <string name="create_group">Utwórz tajną grupę</string> <string name="create_secret_group_title">Utwórz tajną grupę</string> <string name="set_password_to_export_desc">Baza danych jest zaszyfrowana przy użyciu losowego hasła. Proszę zmienić je przed eksportem.</string> @@ -959,7 +955,7 @@ <string name="feature_offered_item_with_param">zaproponował %s: %2s</string> <string name="only_group_owners_can_enable_voice">Tylko właściciele grup mogą włączyć wiadomości głosowe.</string> <string name="network_use_onion_hosts_no_desc_in_alert">Hosty onion nie będą używane.</string> - <string name="only_your_contact_can_delete">Tylko Twój kontakt może nieodwracalnie usunąć wiadomości (możesz oznaczyć je do usunięcia).</string> + <string name="only_your_contact_can_delete">Tylko Twój kontakt może nieodwracalnie usunąć wiadomości (możesz oznaczyć je do usunięcia). (24 godziny)</string> <string name="restore_passphrase_not_found_desc">Hasło nie zostało znalezione w Keystore, wprowadź je ręcznie. Może się tak zdarzyć, gdy przywrócisz dane aplikacji za pomocą narzędzia do kopii zapasowych. Jeśli tak nie jest, skontaktuj się z programistami.</string> <string name="group_members_can_send_disappearing">Członkowie grupy mogą wysyłać znikające wiadomości.</string> <string name="group_members_can_send_voice">Członkowie grupy mogą wysyłać wiadomości głosowe.</string> @@ -1000,9 +996,7 @@ <string name="simplex_link_contact">Adres kontaktowy SimpleX</string> <string name="stop_chat_to_export_import_or_delete_chat_database">Zatrzymaj czat, aby wyeksportować, zaimportować lub usunąć bazę danych czatu. Podczas zatrzymania chatu nie będzie można odbierać ani wysyłać wiadomości.</string> <string name="smp_servers_test_some_failed">Niektóre serwery nie przeszły testu:</string> - <string name="should_be_at_least_one_profile">Powinien istnieć co najmniej jeden profil użytkownika.</string> <string name="thank_you_for_installing_simplex">Dziękujemy za zainstalowanie SimpleX Chat!</string> - <string name="should_be_at_least_one_visible_profile">Powinien istnieć co najmniej jeden widoczny profil użytkownika.</string> <string name="moderate_message_will_be_marked_warning">Wiadomość zostanie oznaczona jako moderowana dla wszystkich członków.</string> <string name="member_role_will_be_changed_with_notification">Rola zostanie zmieniona na \"%s\". Wszyscy w grupie zostaną powiadomieni.</string> <string name="delete_files_and_media_desc">Tego działania nie można cofnąć - wszystkie odebrane i wysłane pliki oraz media zostaną usunięte. Obrazy o niskiej rozdzielczości pozostaną.</string> @@ -1412,7 +1406,7 @@ <string name="rcv_group_and_other_events">i %d innych wydarzeń</string> <string name="connect_plan_connect_via_link">Połączyć przez link?</string> <string name="connect_plan_already_joining_the_group">Już dołączono do grupy!</string> - <string name="moderated_items_description">%d wiadomości zmoderowanych przez %s</string> + <string name="moderated_items_description">%1$d wiadomości zmoderowanych przez %2$s</string> <string name="connect_plan_connect_to_yourself">Połączyć się ze sobą?</string> <string name="correct_name_to">Poprawić nazwę do %s?</string> <string name="delete_messages__question">Usunąć %d wiadomości?</string> @@ -1427,12 +1421,12 @@ <string name="blocked_item_description">zablokowany</string> <string name="expand_verb">Rozszerz</string> <string name="connect_plan_repeat_connection_request">Powtórzyć prośbę połączenia?</string> - <string name="connect_plan_you_are_already_connecting_to_vName">Już jesteś połączony z %1$s.</string> + <string name="connect_plan_you_are_already_connecting_to_vName"><![CDATA[Już jesteś połączony z <b>%1$s</b>.]]></string> <string name="error_alert_title">Błąd</string> <string name="connect_plan_you_are_already_joining_the_group_via_this_link">Już dołączasz do grupy przez ten link.</string> <string name="group_members_2">%s i %s</string> <string name="connect_plan_join_your_group">Dołączyć do twojej grupy?</string> - <string name="connect_plan_you_are_already_joining_the_group_vName">Już dołączasz do grupy %1$s.</string> + <string name="connect_plan_you_are_already_joining_the_group_vName"><![CDATA[Już dołączasz do grupy <b>%1$s</b>.]]></string> <string name="connect_plan_this_is_your_own_one_time_link">To jest twój jednorazowy link!</string> <string name="connect_plan_group_already_exists">Grupa już istnieje!</string> <string name="video_decoding_exception_desc">Wideo nie może zostać zdekodowane, spróbuj inne wideo lub skontaktuj się z deweloperami.</string> @@ -1440,7 +1434,7 @@ <string name="group_members_n">%s, %s i %d członków</string> <string name="unblock_member_button">Odblokuj członka</string> <string name="contact_tap_to_connect">Dotknij aby połączyć</string> - <string name="connect_plan_you_are_already_in_group_vName">Już jesteś w grupie %1$s.</string> + <string name="connect_plan_you_are_already_in_group_vName"><![CDATA[Już jesteś w grupie <b>%1$s</b>.]]></string> <string name="connect_plan_this_is_your_own_simplex_address">To jest twój własny adres SimpleX!</string> <string name="remove_member_button">Usuń członka</string> <string name="unblock_member_question">Odblokować członka?</string> @@ -1452,7 +1446,7 @@ <string name="error_sending_message_contact_invitation">Błąd wysyłania zaproszenia</string> <string name="non_content_uri_alert_text">Udostępniłeś nieprawidłową ścieżkę pliku. Zgłoś problem do deweloperów aplikacji.</string> <string name="invalid_name">Nieprawidłowa nazwa!</string> - <string name="connect_plan_this_is_your_link_for_group_vName">To jest twój link zaproszenia do grupy %1$s!</string> + <string name="connect_plan_this_is_your_link_for_group_vName"><![CDATA[To jest twój link zaproszenia do grupy <b>%1$s</b>!]]></string> <string name="unblock_member_confirmation">Odblokuj</string> <string name="non_content_uri_alert_title">Nieprawidłowa ścieżka pliku</string> <string name="connect_plan_you_have_already_requested_connection_via_this_address">Już prosiłeś o połączenie na ten adres!</string> @@ -1522,4 +1516,120 @@ <string name="disconnect_desktop_question">Rozłączyć komputer?</string> <string name="loading_remote_file_desc">Proszę poczekać na załadowanie pliku z połączonego telefonu</string> <string name="verify_connection">Zweryfikuj połączenie</string> + <string name="refresh_qr_code">Odświerz</string> + <string name="you_can_make_address_visible_via_settings">Możesz ustawić go jako widoczny dla swoich kontaktów SimpleX w Ustawieniach.</string> + <string name="random_port">Losowy</string> + <string name="error_showing_content">błąd wyświetlania zawartości</string> + <string name="error_showing_message">błąd wyświetlania wiadomości</string> + <string name="open_port_in_firewall_desc">Aby umożliwić aplikacji mobilnej łączenie się z komputerem, otwórz ten port w zaporze sieciowej, jeśli jest ona włączona</string> + <string name="create_chat_profile">Utwórz profil czatu</string> + <string name="app_was_crashed">Widok uległ awarii</string> + <string name="open_port_in_firewall_title">Otwórz port w zaporze</string> + <string name="disconnect_remote_hosts">Rozłącz telefony</string> + <string name="no_connected_mobile">Brak połączonych telefonów</string> + <string name="recent_history_is_not_sent_to_new_members">Historia nie jest wysyłana do nowych członków.</string> + <string name="retry_verb">Ponów</string> + <string name="camera_not_available">Kamera nie dostępna</string> + <string name="enable_sending_recent_history">Wysyłaj do 100 ostatnich wiadomości do nowych członków.</string> + <string name="add_contact_button_to_create_link_or_connect_via_link"><![CDATA[<b>Dodaj kontakt</b>: aby utworzyć nowy link z zaproszeniem lub połączyć się za pomocą otrzymanego linku.]]></string> + <string name="disable_sending_recent_history">Nie wysyłaj historii do nowych członków.</string> + <string name="or_show_this_qr_code">Lub pokaż ten kod</string> + <string name="recent_history_is_sent_to_new_members">Do nowych członków wysyłanych jest do 100 ostatnich wiadomości</string> + <string name="code_you_scanned_is_not_simplex_link_qr_code">Kod, który zeskanowałeś nie jest kodem QR linku SimpleX.</string> + <string name="the_text_you_pasted_is_not_a_link">Tekst, który wkleiłeś nie jest linkiem SimpleX.</string> + <string name="enable_camera_access">Włącz dostęp do kamery</string> + <string name="you_can_view_invitation_link_again">Możesz zobaczyć link zaproszenia ponownie w szczegółach połączenia.</string> + <string name="keep_unused_invitation_question">Zachować nieużyte zaproszenie?</string> + <string name="share_this_1_time_link">Udostępnij ten jednorazowy link</string> + <string name="create_group_button_to_create_new_group"><![CDATA[<b>Utwórz grupę</b>: aby utworzyć nową grupę.]]></string> + <string name="recent_history">Widoczna historia</string> + <string name="la_app_passcode">Pin aplikacji</string> + <string name="new_chat">Nowy czat</string> + <string name="loading_chats">Ładowanie czatów…</string> + <string name="creating_link">Tworzenie linku…</string> + <string name="or_scan_qr_code">Lub zeskanuj kod QR</string> + <string name="invalid_qr_code">Nieprawidłowy kod QR</string> + <string name="add_contact_tab">Dodaj kontakt</string> + <string name="tap_to_scan">Dotknij, aby zeskanować</string> + <string name="keep_invitation_link">Zachowaj</string> + <string name="tap_to_paste_link">Dotknij, aby wkleić link</string> + <string name="search_or_paste_simplex_link">Wyszukaj lub wklej link SimpleX</string> + <string name="v5_5_private_notes">Prywatne notatki</string> + <string name="v5_5_message_delivery">Ulepszona dostawa wiadomości</string> + <string name="v5_5_new_interface_languages">Węgierski i turecki interfejs</string> + <string name="v5_5_message_delivery_descr">Ze zmniejszonym zużyciem baterii.</string> + <string name="remote_ctrl_error_bad_state">Połączenie z komputerem jest w złym stanie</string> + <string name="remote_ctrl_error_bad_invitation">Komputer ma zły kod zaproszenia</string> + <string name="remote_ctrl_error_busy">Komputer jest zajęty</string> + <string name="remote_ctrl_error_disconnected">Komputer został odłączony</string> + <string name="error_deleting_note_folder">Błąd usuwania prywatnych notatek</string> + <string name="possible_slow_function_title">Wolne funkcje</string> + <string name="clear_note_folder_question">Wyczyścić prywatne notatki?</string> + <string name="developer_options_section">Opcje deweloperskie</string> + <string name="show_slow_api_calls">Pokaż wolne zapytania API</string> + <string name="rcv_group_event_member_blocked">zablokowany %s</string> + <string name="start_chat_question">Uruchomić czat?</string> + <string name="rcv_group_event_member_unblocked">odblokuj %s</string> + <string name="snd_group_event_member_blocked">zablokowałeś %s</string> + <string name="snd_group_event_member_unblocked">odblokowałeś %s</string> + <string name="profile_update_event_member_name_changed">członek %1$s zmienił na %2$s</string> + <string name="profile_update_event_set_new_address">ustaw nowy adres kontaktu</string> + <string name="profile_update_event_updated_profile">zaktualizowano profil</string> + <string name="past_member_vName">Były członek %1$s</string> + <string name="block_for_all_question">Zablokować członka dla wszystkich?</string> + <string name="info_row_created_at">Utworzony o</string> + <string name="saved_message_title">Zachowano wiadomość</string> + <string name="unblock_for_all">Odblokuj dla wszystkich</string> + <string name="unblock_for_all_question">Odblokować członka dla wszystkich?</string> + <string name="error_blocking_member_for_all">Błąd blokowania członka dla wszystkich</string> + <string name="v5_5_simpler_connect_ui">Wklej link, aby połączyć!</string> + <string name="v5_5_private_notes_descr">Z zaszyfrowanymi plikami i multimediami.</string> + <string name="v5_5_simpler_connect_ui_descr">Pasek wyszukiwania akceptuje linki zaproszenia.</string> + <string name="v5_5_join_group_conversation_descr">Ostatnia historia i ulepszony bot adresowy.</string> + <string name="agent_critical_error_title">Krytyczny błąd</string> + <string name="agent_critical_error_desc">Proszę zgłosić to do deweloperów: +\n%s +\n +\nZalecane jest zrestartowanie aplikacji.</string> + <string name="agent_internal_error_desc">Proszę zgłosić to do deweloperów: +\n%s</string> + <string name="restart_chat_button">Zrestartuj czat</string> + <string name="clear_note_folder_warning">Wszystkie wiadomości zostaną usunięte – nie można tego cofnąć!</string> + <string name="member_info_member_blocked">zablokowany</string> + <string name="blocked_by_admin_item_description">zablokowany przez administratora</string> + <string name="member_blocked_by_admin">Zablokowany przez admina</string> + <string name="block_for_all">Zablokuj dla wszystkich</string> + <string name="chat_is_stopped_you_should_transfer_database">Czat został zatrzymany. Jeśli korzystałeś już z tej bazy danych na innym urządzeniu, powinieneś przenieść ją z powrotem przed rozpoczęciem czatu.</string> + <string name="agent_internal_error_title">Wewnętrzny błąd</string> + <string name="v5_5_join_group_conversation">Dołącz do grupowej rozmowy</string> + <string name="share_text_created_at">Utworzony o: %s</string> + <string name="remote_ctrl_error_bad_version">Komputer ma niewspieraną wersję. Proszę upewnić się, że używasz tych samych wersji na obu urządzeniach</string> + <string name="blocked_by_admin_items_description">%d wiadomości zablokowanych przez admina</string> + <string name="error_creating_message">Błąd tworzenia wiadomości</string> + <string name="possible_deadlock_desc">Wykonanie kodu zajmuje za dużo czasu: %1$d sekund. Prawdopodobnie aplikacja jest zamrożona: %2$s</string> + <string name="possible_slow_function_desc">Wykonanie kodu zajmuje za dużo czasu: %1$d sekund: %2$s</string> + <string name="note_folder_local_display_name">Prywatne notatki</string> + <string name="group_member_status_unknown">nieznany status</string> + <string name="show_internal_errors">Pokaż błędy wewnętrzne</string> + <string name="remote_ctrl_error_timeout">Osiągnięto limit czasu podczas łączenia z komputerem</string> + <string name="failed_to_create_user_invalid_title">Nieprawidłowa nazwa wyświetlana!</string> + <string name="failed_to_create_user_invalid_desc">Nazwa wyświetlana jest nieprawidłowa. Proszę wybrać inną nazwę.</string> + <string name="remote_host_was_disconnected_title">Połączenie zatrzymane</string> + <string name="remote_ctrl_was_disconnected_title">Połączenie zatrzymane</string> + <string name="remote_host_disconnected_from"><![CDATA[Odłączono od telefonu <b>%s</b> z powodu: %s]]></string> + <string name="remote_host_error_missing"><![CDATA[Brakuje telefonu <b>%s</b>]]></string> + <string name="remote_host_error_inactive"><![CDATA[Telefon <b>%s</b> jest nieaktywny]]></string> + <string name="remote_host_error_bad_version"><![CDATA[Telefon <b>%s</b> ma niewspieraną wersję. Proszę, upewnij się, że używasz tej samej wersji na obydwu urządzeniach]]></string> + <string name="group_member_status_unknown_short">nieznany</string> + <string name="possible_deadlock_title">Blokada</string> + <string name="profile_update_event_contact_name_changed">kontakt %1$s zmieniony na %2$s</string> + <string name="profile_update_event_removed_address">usunięto adres kontaktu</string> + <string name="profile_update_event_removed_picture">usunięto zdjęcie profilu</string> + <string name="profile_update_event_set_new_picture">ustaw nowe zdjęcie profilu</string> + <string name="remote_host_error_bad_state"><![CDATA[Połączenie z telefonem <b>%s</b> jest w złym stanie]]></string> + <string name="remote_ctrl_disconnected_with_reason">Odłączono z powodu: %s</string> + <string name="remote_host_error_busy"><![CDATA[Telefon <b>%s</b> jest zajęty]]></string> + <string name="remote_host_error_timeout"><![CDATA[Osiągnięto limit czasu podczas łączenia z telefonem <b>%s</b>]]></string> + <string name="remote_ctrl_error_inactive">Komputer jest nieaktywny</string> + <string name="remote_host_error_disconnected"><![CDATA[Telefon <b>%s</b> został rozłączony]]></string> </resources> \ No newline at end of file diff --git a/apps/multiplatform/common/src/commonMain/resources/MR/pt-rBR/strings.xml b/apps/multiplatform/common/src/commonMain/resources/MR/pt-rBR/strings.xml index 622ad8b2d6..bf7d29c9c3 100644 --- a/apps/multiplatform/common/src/commonMain/resources/MR/pt-rBR/strings.xml +++ b/apps/multiplatform/common/src/commonMain/resources/MR/pt-rBR/strings.xml @@ -24,8 +24,6 @@ <string name="icon_descr_cancel_live_message">Cancelar mensagem ao vivo</string> <string name="back">Voltar</string> <string name="choose_file">Arquivo</string> - <string name="add_new_contact_to_create_one_time_QR_code"><![CDATA[<b>Adicionar novo contato</b>: para criar seu QR code de uso único para seu contato.]]></string> - <string name="scan_QR_code_to_connect_to_contact_who_shows_QR_code"><![CDATA[<b>Escanear código QR</b>: para se conectar ao seu contato que mostra o código QR para você.]]></string> <string name="accept_contact_button">Aceitar</string> <string name="clear_chat_question">Limpar chat\?</string> <string name="clear_verb">Limpar</string> @@ -374,7 +372,6 @@ <string name="auth_device_authentication_is_disabled_turning_off">A autenticação do dispositivo está desativada. Desativando o bloqueio SimpleX.</string> <string name="for_everybody">Para todos</string> <string name="notification_preview_mode_hidden">Oculto</string> - <string name="create_one_time_link">Gerar um link de convite de uso único.</string> <string name="how_to_use_your_servers">Como usar seus servidores</string> <string name="import_database_confirmation">Importar</string> <string name="import_database_question">Importar banco de dados de chat\?</string> @@ -709,7 +706,6 @@ <string name="no_contacts_to_add">Sem contatos para adicionar</string> <string name="member_role_will_be_changed_with_notification">A função será alterada para \"%s\". Todos no grupo serão notificados.</string> <string name="user_mute">Mutar</string> - <string name="should_be_at_least_one_visible_profile">Deve haver pelo menos um perfil de usuário visível.</string> <string name="only_you_can_send_voice">Somente você pode enviar mensagens de voz.</string> <string name="only_your_contact_can_send_voice">Somente seu contato pode enviar mensagens de voz.</string> <string name="prohibit_message_deletion">Proibir a exclusão irreversível de mensagens.</string> @@ -742,9 +738,7 @@ <string name="incompatible_database_version">Versão do banco de dados incompatível</string> <string name="button_remove_member">Remover membro</string> <string name="group_main_profile_sent">Seu perfil de chat será enviado aos membros do grupo</string> - <string name="cant_delete_user_profile">Não é possível excluir o perfil do usuário!</string> <string name="make_profile_private">Torne o perfil privado!</string> - <string name="should_be_at_least_one_profile">Deve haver pelo menos um perfil de usuário.</string> <string name="v4_2_security_assessment">Avaliação de segurança</string> <string name="v4_5_multiple_chat_profiles_descr">Nomes diferentes, avatares e isolamento de transporte.</string> <string name="v4_2_auto_accept_contact_requests_desc">Com mensagem de boas-vindas opcional.</string> diff --git a/apps/multiplatform/common/src/commonMain/resources/MR/pt/strings.xml b/apps/multiplatform/common/src/commonMain/resources/MR/pt/strings.xml index 072eb97ebf..438d6832c9 100644 --- a/apps/multiplatform/common/src/commonMain/resources/MR/pt/strings.xml +++ b/apps/multiplatform/common/src/commonMain/resources/MR/pt/strings.xml @@ -211,7 +211,6 @@ <string name="info_row_group">Grupo</string> <string name="icon_descr_audio_on">Áudio ligado</string> <string name="authentication_cancelled">Autenticação cancelada</string> - <string name="add_new_contact_to_create_one_time_QR_code"><![CDATA[<b> Adicionar novo contato</b>: para criar o seu código QR de utilização única para o seu contato.]]></string> <string name="onboarding_notifications_mode_periodic_desc"><![CDATA[<b> Bom para a bateria </b>. O serviço em segundo plano verifica se há mensagens a cada 10 minutos. Você pode perder chamadas ou mensagens urgentes.]]></string> <string name="turning_off_service_and_periodic">A otimização da bateria está ativa, desativando o serviço em segundo plano e os pedidos periódicos de novas mensagens. Você pode reativá-los através das definições.</string> <string name="onboarding_notifications_mode_off_desc"><![CDATA[<b>Melhor para a bateria</b>. Apenas receberá notificações enquanto a app estiver em execução (SEM serviço em segundo plano)]]></string> @@ -225,7 +224,6 @@ <string name="calls_prohibited_with_this_contact">Chamadas de áudio/vídeo são proibidas.</string> <string name="notifications_mode_service_desc">O serviço em segundo plano está sempre em execução - as notificações serão exibidas assim que as mensagens estiverem disponíveis.</string> <string name="la_authenticate">Autenticar</string> - <string name="scan_QR_code_to_connect_to_contact_who_shows_QR_code"><![CDATA[<b>Leia o código QR </b>: para se conectar ao seu contato que lhe mostra o código QR.]]></string> <string name="callstatus_ended">chamada finalizada %1$s</string> <string name="callstatus_calling">a chamar…</string> <string name="callstatus_error">erro de chamada</string> @@ -241,7 +239,6 @@ <string name="call_on_lock_screen">Chamadas no ecrã de bloqueio:</string> <string name="alert_title_cant_invite_contacts">Não é possível convidar contatos!</string> <string name="change_verb">Alterar</string> - <string name="cant_delete_user_profile">Não é possível eliminar o perfil do utilizador!</string> <string name="feature_cancelled_item">cancelado %s</string> <string name="cannot_receive_file">Não é possível receber o ficheiro</string> <string name="icon_descr_cancel_image_preview">Cancelar pré-visualização da imagem</string> @@ -366,7 +363,6 @@ <string name="connection_error">Erro de conexão</string> <string name="connection_local_display_name">conexão %1$d</string> <string name="contact_already_exists">O contato já existe</string> - <string name="create_one_time_link">Criar convite de ligação de utilização única</string> <string name="one_time_link">Convite de ligação de utilização única</string> <string name="save_servers_button">Salvar</string> <string name="settings_section_title_incognito">Modo anónimo</string> diff --git a/apps/multiplatform/common/src/commonMain/resources/MR/ro/strings.xml b/apps/multiplatform/common/src/commonMain/resources/MR/ro/strings.xml new file mode 100644 index 0000000000..3e06927ddc --- /dev/null +++ b/apps/multiplatform/common/src/commonMain/resources/MR/ro/strings.xml @@ -0,0 +1,72 @@ +<?xml version="1.0" encoding="utf-8"?> +<resources> + <string name="moderated_items_description">%1$d mesaje moderate de %2$s</string> + <string name="abort_switch_receiving_address_question">Întrerupi schimbarea adresei?</string> + <string name="send_disappearing_message_30_seconds">30 secunde</string> + <string name="accept_contact_button">Acceptă</string> + <string name="accept_contact_incognito_button">Acceptă incognito</string> + <string name="smp_servers_add">Adaugă server…</string> + <string name="network_settings">Setări de rețea avansate</string> + <string name="contact_wants_to_connect_via_call">%1$s dorește să se conecteze cu tine prin</string> + <string name="accept_call_on_lock_screen">Acceptă</string> + <string name="alert_text_decryption_error_too_many_skipped">%1$d mesaje omise.</string> + <string name="chat_item_ttl_month">1 lună</string> + <string name="chat_item_ttl_week">1 săptămână</string> + <string name="group_member_role_admin">administrator</string> + <string name="color_primary_variant">Accent adițional</string> + <string name="color_secondary_variant">Adițional secundar</string> + <string name="accept_feature">Acceptă</string> + <string name="v5_3_new_interface_languages">6 limbi noi pentru interfață</string> + <string name="alert_text_decryption_error_n_messages_failed_to_decrypt">%1$d mesaje nu au putut fi decriptate.</string> + <string name="integrity_msg_skipped">%1$d mesaj(e) omis(e)</string> + <string name="group_info_section_title_num_members">%1$s MEMBRI</string> + <string name="chat_item_ttl_day">1 zi</string> + <string name="send_disappearing_message_1_minute">1 minut</string> + <string name="one_time_link_short">link de unică folosință</string> + <string name="send_disappearing_message_5_minutes">5 minute</string> + <string name="about_simplex">Despre SimpleX</string> + <string name="learn_more_about_address">Despre adresa SimpleX</string> + <string name="about_simplex_chat">Despre SimpleX Chat</string> + <string name="above_then_preposition_continuation">deasupra, apoi:</string> + <string name="color_primary">Accent</string> + <string name="accept">Acceptă</string> + <string name="accept_connection_request__question">Accepți cererea de conexiune?</string> + <string name="add_contact_tab">Adaugă contact</string> + <string name="callstatus_accepted">apel acceptat</string> + <string name="smp_servers_preset_add">Adaugă servere prestabilite</string> + <string name="users_add">Adaugă profil</string> + <string name="address_section_title">Adresă</string> + <string name="v4_3_improved_server_configuration_desc">Adaugă servere prin scanare de coduri QR.</string> + <string name="smp_servers_add_to_another_device">Adaugă la un alt dispozitiv</string> + <string name="button_add_welcome_message">Adaugă mesaj de întâmpinare</string> + <string name="conn_event_ratchet_sync_started">acceptând criptarea…</string> + <string name="snd_conn_event_ratchet_sync_started">acceptând criptarea pentru %s…</string> + <string name="v4_2_group_links_desc">Administratorii pot crea linkuri de participare la grupuri.</string> + <string name="v5_2_more_things">Câteva lucruri în plus</string> + <string name="all_app_data_will_be_cleared">Toate datele aplicației sunt șterse.</string> + <string name="abort_switch_receiving_address_desc">Schimbarea de adresă va fi întreruptă. Se va folosi vechea adresa de primire.</string> + <string name="add_address_to_your_profile">Adaugă adresa la profil, astfel încât contactele să o poată partaja cu alte persoane. Profilul reînoit va fi comunicat contactelor.</string> + <string name="network_enable_socks_info">Accesezi serverele prin proxy SOCKS cu portul %d? Proxyul trebuie pornit înaintea activării acestei opțiuni.</string> + <string name="abort_switch_receiving_address">Întrerupe schimbarea adresei</string> + <string name="abort_switch_receiving_address_confirm">Întrerupe</string> + <string name="users_delete_all_chats_deleted">Toate conversațiile și mesajele vor fi șterse - operațiunea este definitivă!</string> + <string name="clear_note_folder_warning">Toate mesajele vor fi șterse - operațiunea este definitivă!</string> + <string name="allow_message_reactions_only_if">Permite reacții la mesaje doar dacă și contactul tău le permite.</string> + <string name="allow_to_delete_messages">Permite ștergerea ireversibila a mesajelor trimise. (24 ore)</string> + <string name="allow_to_send_files">Permite trimiterea de fișiere și media.</string> + <string name="v5_1_self_destruct_passcode_descr">Toate datele sunt șterse când este introdusă.</string> + <string name="all_group_members_will_remain_connected">Toți membrii grupului vor rămâne conectați.</string> + <string name="clear_chat_warning">Toate mesajele vor fi șterse - operațiunea este definitivă! Mesajele vor fi șterse DOAR pentru tine.</string> + <string name="block_member_desc">Toate mesajele noi de la %s vor fi ascunse!</string> + <string name="turn_off_battery_optimization_button">Permite</string> + <string name="allow_verb">Permite</string> + <string name="allow_calls_only_if">Permite apeluri doar dacă le permite contactul tău.</string> + <string name="allow_voice_messages_question">Permiți mesaje vocale?</string> + <string name="allow_voice_messages_only_if">Permite mesajele vocale numai dacă le permite și contactul tău.</string> + <string name="allow_irreversible_message_deletion_only_if">Permite ștergerea mesajelor ireversibile doar dacă și contactul tău îți permite ție. (24 ore)</string> + <string name="allow_message_reactions">Permite reacții la mesaje.</string> + <string name="allow_direct_messages">Permite trimiterea de mesaje directe membrilor.</string> + <string name="allow_to_send_disappearing">Permite trimiterea de mesaje efemere.</string> + <string name="allow_to_send_voice">Permite trimiterea de mesaje vocale.</string> + <string name="allow_disappearing_messages_only_if">Permite mesaje efemere doar dacă le permite contactul tău.</string> +</resources> \ No newline at end of file diff --git a/apps/multiplatform/common/src/commonMain/resources/MR/ru/strings.xml b/apps/multiplatform/common/src/commonMain/resources/MR/ru/strings.xml index 9e8bd0af8c..af0f3c6ee7 100644 --- a/apps/multiplatform/common/src/commonMain/resources/MR/ru/strings.xml +++ b/apps/multiplatform/common/src/commonMain/resources/MR/ru/strings.xml @@ -267,12 +267,10 @@ <string name="to_start_a_new_chat_help_header">Чтобы начать новый чат</string> <string name="chat_help_tap_button">Нажмите кнопку</string> <string name="above_then_preposition_continuation">сверху, затем:</string> - <string name="add_new_contact_to_create_one_time_QR_code"><![CDATA[<b>Добавить новый контакт</b>: чтобы создать одноразовый QR код/ссылку для Вашего контакта.]]></string> - <string name="scan_QR_code_to_connect_to_contact_who_shows_QR_code"><![CDATA[<b>Сканировать QR код</b>: чтобы соединиться с контактом, который показывает Вам QR код.]]></string> <string name="to_connect_via_link_title">Чтобы соединиться через ссылку</string> <string name="if_you_received_simplex_invitation_link_you_can_open_in_browser">Если Вы получили ссылку с приглашением из SimpleX Chat, Вы можете открыть ее в браузере:</string> <string name="desktop_scan_QR_code_from_app_via_scan_QR_code"><![CDATA[💻 на компьютере: сосканируйте показанный QR код из приложения через <b>Сканировать QR код</b>.]]></string> - <string name="mobile_tap_open_in_mobile_app_then_tap_connect_in_app"><![CDATA[📱 на мобильном: намжите кнопку <b>Open in mobile app</b> на веб странице, затем нажмите <b>Соединиться</b> в приложении.]]></string> + <string name="mobile_tap_open_in_mobile_app_then_tap_connect_in_app"><![CDATA[📱 на мобильном: нажмите кнопку <b>Open in mobile app</b> на веб странице, затем нажмите <b>Соединиться</b> в приложении.]]></string> <!-- Contact Request Alert Dialogue - CharListNavLinkView.kt --> <string name="accept_connection_request__question">Принять запрос на соединение?</string> <string name="if_you_choose_to_reject_the_sender_will_not_be_notified">Отправителю НЕ будет послано уведомление, если Вы отклоните запрос на соединение.</string> @@ -301,7 +299,8 @@ <string name="connection_you_accepted_will_be_cancelled">Подтвержденное соединение будет отменено!</string> <!-- Connection Pending Alert Dialogue - ChatListNavLinkView.kt --> <string name="alert_title_contact_connection_pending">Соединение еще не установлено!</string> - <string name="alert_text_connection_pending_they_need_to_be_online_can_delete_and_retry">Ваш контакт должен быть в сети чтобы установить соединение.\nВы можете отменить соединение и удалить контакт (и попробовать позже с другой ссылкой).</string> + <string name="alert_text_connection_pending_they_need_to_be_online_can_delete_and_retry">Ваш контакт должен быть в сети, чтобы установить соединение. +\nВы можете отменить соединение и удалить контакт (и попробовать позже с другой ссылкой).</string> <!-- Contact Request Information - ContactRequestView.kt --> <string name="contact_wants_to_connect_with_you">хочет соединиться с Вами!</string> <!-- Image Placeholder - ChatInfoImage.kt --> @@ -339,7 +338,6 @@ <string name="connect_button">Соединиться</string> <string name="paste_button">Вставить</string> <!-- CreateLinkView.kt --> - <string name="create_one_time_link">Создать одноразовую ссылку</string> <string name="one_time_link">Одноразовая ссылка</string> <!-- settings - SettingsView.kt --> <string name="your_settings">Настройки</string> @@ -490,7 +488,7 @@ <!-- SetNotificationsMode.kt --> <string name="use_chat">Использовать чат</string> <!-- MakeConnection --> - <string name="paste_the_link_you_received">Вставить полученную ссылку</string> + <string name="paste_the_link_you_received">Вставьте полученную ссылку</string> <!-- Call --> <string name="incoming_video_call">Входящий видеозвонок</string> <string name="incoming_audio_call">Входящий аудиозвонок</string> @@ -875,15 +873,15 @@ <string name="feature_enabled_for_contact">включено для контакта</string> <string name="feature_off">выключено</string> <string name="feature_received_prohibited">получено, не разрешено</string> - <string name="allow_your_contacts_irreversibly_delete">Разрешить Вашим контактам необратимо удалять отправленные сообщения.</string> - <string name="allow_irreversible_message_deletion_only_if">Разрешить необратимое удаление сообщений, только если Ваш контакт разрешает это Вам.</string> + <string name="allow_your_contacts_irreversibly_delete">Разрешить Вашим контактам необратимо удалять отправленные сообщения. (24 часа)</string> + <string name="allow_irreversible_message_deletion_only_if">Разрешить необратимое удаление сообщений, только если Ваш контакт разрешает это Вам. (24 часа)</string> <string name="contacts_can_mark_messages_for_deletion">Контакты могут помечать сообщения для удаления; Вы сможете просмотреть их.</string> <string name="allow_your_contacts_to_send_voice_messages">Разрешить Вашим контактам отправлять голосовые сообщения.</string> <string name="allow_voice_messages_only_if">Разрешить голосовые сообщения, только если их разрешает Ваш контакт.</string> <string name="prohibit_sending_voice_messages">Запретить отправлять голосовые сообщений.</string> - <string name="both_you_and_your_contacts_can_delete">Вы и Ваш контакт можете необратимо удалять отправленные сообщения.</string> - <string name="only_you_can_delete_messages">Только Вы можете необратимо удалять сообщения (Ваш контакт может помечать их на удаление).</string> - <string name="only_your_contact_can_delete">Только Ваш контакт может необратимо удалять сообщения (Вы можете помечать их на удаление).</string> + <string name="both_you_and_your_contacts_can_delete">Вы и Ваш контакт можете необратимо удалять отправленные сообщения. (24 часа)</string> + <string name="only_you_can_delete_messages">Только Вы можете необратимо удалять сообщения (Ваш контакт может помечать их на удаление). (24 часа)</string> + <string name="only_your_contact_can_delete">Только Ваш контакт может необратимо удалять сообщения (Вы можете помечать их на удаление). (24 часа)</string> <string name="message_deletion_prohibited">Необратимое удаление сообщений запрещено в этой группе.</string> <string name="both_you_and_your_contact_can_send_voice">Вы и Ваш контакт можете отправлять голосовые сообщения.</string> <string name="only_you_can_send_voice">Только Вы можете отправлять голосовые сообщения.</string> @@ -891,13 +889,13 @@ <string name="voice_prohibited_in_this_chat">Голосовые сообщения запрещены в этом чате.</string> <string name="allow_direct_messages">Разрешить посылать прямые сообщения членам группы.</string> <string name="prohibit_direct_messages">Запретить посылать прямые сообщения членам группы.</string> - <string name="allow_to_delete_messages">Разрешить необратимо удалять отправленные сообщения.</string> + <string name="allow_to_delete_messages">Разрешить необратимо удалять отправленные сообщения. (24 часа)</string> <string name="prohibit_message_deletion">Запретить необратимое удаление сообщений.</string> <string name="allow_to_send_voice">Разрешить отправлять голосовые сообщения.</string> <string name="prohibit_sending_voice">Запретить отправлять голосовые сообщений.</string> <string name="group_members_can_send_dms">Члены группы могут посылать прямые сообщения.</string> <string name="direct_messages_are_prohibited_in_chat">Прямые сообщения между членами группы запрещены.</string> - <string name="group_members_can_delete">Члены группы могут необратимо удалять отправленные сообщения.</string> + <string name="group_members_can_delete">Члены группы могут необратимо удалять отправленные сообщения. (24 часа)</string> <string name="message_deletion_prohibited_in_chat">Необратимое удаление сообщений запрещено в этой группе.</string> <string name="group_members_can_send_voice">Члены группы могут отправлять голосовые сообщения.</string> <string name="voice_messages_are_prohibited">Голосовые сообщения запрещены в этой группе.</string> @@ -1047,8 +1045,6 @@ <string name="v4_6_audio_video_calls">Аудио и видео звонки</string> <string name="error_saving_user_password">Ошибка при сохранении пароля пользователя</string> <string name="smp_save_servers_question">Сохранить серверы\?</string> - <string name="should_be_at_least_one_profile">Должен быть хотя бы один профиль пользователя.</string> - <string name="should_be_at_least_one_visible_profile">Должен быть хотя бы один открытый профиль пользователя.</string> <string name="to_reveal_profile_enter_password">Чтобы показать Ваш скрытый профиль, введите пароль в поле поиска на странице Ваши профили.</string> <string name="user_unmute">Уведомлять</string> <string name="group_welcome_title">Приветственное сообщение</string> @@ -1057,7 +1053,6 @@ <string name="button_welcome_message">Приветственное сообщение</string> <string name="save_and_update_group_profile">Сохранить сообщение и обновить группу</string> <string name="muted_when_inactive">Без звука, когда не активный!</string> - <string name="cant_delete_user_profile">Нельзя удалить профиль пользователя!</string> <string name="enter_password_to_show">Введите пароль в поиске!</string> <string name="save_profile_password">Сохранить пароль профиля</string> <string name="v4_6_chinese_spanish_interface">Китайский и Испанский интерфейс</string> @@ -1518,7 +1513,7 @@ <string name="connect_plan_connect_via_link">Соединиться через ссылку?</string> <string name="v5_4_incognito_groups">Инкогнито группы</string> <string name="connect_plan_already_joining_the_group">Вступление в группу уже начато!</string> - <string name="moderated_items_description">%d сообщений модерировано членом %s</string> + <string name="moderated_items_description">%1$d сообщений модерировано членом %2$s</string> <string name="remote_host_was_disconnected_toast"><![CDATA[Мобильный <b>%s</b> был отключен]]></string> <string name="v5_4_better_groups_descr">Быстрое вступление и надежная доставка сообщений.</string> <string name="connect_plan_connect_to_yourself">Соединиться с самим собой?</string> @@ -1566,9 +1561,9 @@ <string name="block_member_desc">Все новые сообщения от %s будут скрыты!</string> <string name="desktop_app_version_is_incompatible">Версия настольного приложения %s несовместима с этим приложением.</string> <string name="blocked_item_description">заблокировано</string> - <string name="connect_plan_you_are_already_connecting_to_vName">Вы уже соединяетесь с %1$s.</string> + <string name="connect_plan_you_are_already_connecting_to_vName"><![CDATA[Вы уже соединяетесь с <b>%1$s</b>.]]></string> <string name="connect_plan_you_are_already_joining_the_group_via_this_link">Вы уже вступаете в группу по этой ссылке.</string> - <string name="connect_plan_you_are_already_joining_the_group_vName">Вы уже вступаете в группу %1$s.</string> + <string name="connect_plan_you_are_already_joining_the_group_vName"><![CDATA[Вы уже вступаете в группу <b>%1$s</b>.]]></string> <string name="connect_plan_this_is_your_own_one_time_link">Это ваша собственная одноразовая ссылка!</string> <string name="v5_4_link_mobile_desktop_descr">Через безопасный квантово-устойчивый протокол.</string> <string name="v5_4_block_group_members_descr">Чтобы скрыть нежелательные сообщения.</string> @@ -1578,9 +1573,9 @@ <string name="group_members_n">%s, %s и %d членов группы</string> <string name="this_device">Это устройство</string> <string name="unblock_member_button">Разблокировать члена группы</string> - <string name="contact_tap_to_connect">Нажмите чтобы соединиться</string> + <string name="contact_tap_to_connect">Нажмите, чтобы соединиться</string> <string name="this_device_name">Имя этого устройства</string> - <string name="connect_plan_you_are_already_in_group_vName">Вы уже состоите в группе %1$s.</string> + <string name="connect_plan_you_are_already_in_group_vName"><![CDATA[Вы уже состоите в группе <b>%1$s</b>.]]></string> <string name="connect_plan_this_is_your_own_simplex_address">Это ваш собственный адрес SimpleX!</string> <string name="unblock_member_question">Разблокировать члена группы?</string> <string name="settings_section_title_use_from_desktop">Использовать с компьютера</string> @@ -1590,7 +1585,7 @@ <string name="this_device_name_shared_with_mobile">Имя устройства будет доступно подключенному мобильному клиенту.</string> <string name="verify_code_on_mobile">Сверьте код на мобильном</string> <string name="non_content_uri_alert_text">Указан неверный путь к файлу. Сообщите о проблеме разработчикам приложения.</string> - <string name="connect_plan_this_is_your_link_for_group_vName">Это ваша ссылка на группу %1$s!</string> + <string name="connect_plan_this_is_your_link_for_group_vName"><![CDATA[Это ваша ссылка на группу <b>%1$s</b>!]]></string> <string name="verify_code_with_desktop">Сверьте код с компьютером</string> <string name="scan_qr_code_from_desktop">Сканировать QR код с компьютера</string> <string name="unblock_member_confirmation">Разблокировать</string> @@ -1605,4 +1600,119 @@ <string name="not_compatible">Несовместимая версия!</string> <string name="group_member_role_author">автор</string> <string name="multicast_discoverable_via_local_network">Найти через локальную сеть</string> + <string name="refresh_qr_code">Обновить</string> + <string name="random_port">Случайный</string> + <string name="open_port_in_firewall_desc">Чтобы разрешить мобильному приложению подключаться к компьютеру, откройте этот порт в брандмауэре, если он включен</string> + <string name="create_chat_profile">Создать профиль чата</string> + <string name="open_port_in_firewall_title">Открыть порт в брандмауэре</string> + <string name="disconnect_remote_hosts">Отключить мобильные</string> + <string name="no_connected_mobile">Нет подключённых мобильных</string> + <string name="add_contact_tab">Добавить контакт</string> + <string name="v5_5_private_notes">Личные заметки</string> + <string name="v5_5_join_group_conversation">Присоединяйтесь к разговорам в группах</string> + <string name="v5_5_simpler_connect_ui">Вставьте ссылку, чтобы соединиться!</string> + <string name="v5_5_simpler_connect_ui_descr">Поле поиска поддерживает ссылки-приглашения.</string> + <string name="v5_5_join_group_conversation_descr">История сообщений и улучшенный каталог групп.</string> + <string name="remote_host_error_inactive"><![CDATA[Мобильный <b>%s</b> неактивен]]></string> + <string name="remote_ctrl_error_timeout">Превышено максимальное время соединения с компьютером.</string> + <string name="remote_ctrl_error_disconnected">Компьютер отсоединён</string> + <string name="remote_ctrl_error_bad_invitation">Неверный код приглашения у компьютера</string> + <string name="loading_chats">Загрузка чатов…</string> + <string name="enable_camera_access">Включить доступ к камере</string> + <string name="tap_to_scan">Нажмите, чтобы сканировать</string> + <string name="create_group_button_to_create_new_group"><![CDATA[<b>Создать группу</b>: создать новую группу.]]></string> + <string name="disable_sending_recent_history">Не отправлять историю новым членам.</string> + <string name="enable_sending_recent_history">Отправить до 100 последних сообщений новым членам.</string> + <string name="clear_note_folder_warning">Все сообщения будут удалены - это нельзя отменить!</string> + <string name="camera_not_available">Камера недоступна</string> + <string name="la_app_passcode">Код доступа в приложение</string> + <string name="add_contact_button_to_create_link_or_connect_via_link"><![CDATA[<b>Добавить контакт</b>: создать новую ссылку-приглашение или подключиться через полученную ссылку.]]></string> + <string name="chat_is_stopped_you_should_transfer_database">Чат остановлен. Если вы уже использовали эту базу данных на другом устройстве, перенесите ее обратно до запуска чата.</string> + <string name="remote_host_was_disconnected_title">Соединение остановлено</string> + <string name="info_row_created_at">Создано</string> + <string name="keep_invitation_link">Оставить</string> + <string name="share_text_created_at">Создано: %s</string> + <string name="remote_host_error_missing"><![CDATA[Мобильный <b>%s</b> отсутствует]]></string> + <string name="or_show_this_qr_code">Или покажите этот код</string> + <string name="agent_internal_error_desc">Пожалуйста, сообщите об этом разработчикам: +\n%s</string> + <string name="developer_options_section">Опции разработчика</string> + <string name="remote_host_disconnected_from"><![CDATA[Отсоединён от мобильного <b>%s</b> по причине: %s]]></string> + <string name="error_creating_message">Ошибка создания сообщения</string> + <string name="error_deleting_note_folder">Ошибка удаления заметки</string> + <string name="v5_5_new_interface_languages">Венгерский и Турецкий интерфейс</string> + <string name="search_or_paste_simplex_link">Искать или вставьте ссылку SimpleX</string> + <string name="code_you_scanned_is_not_simplex_link_qr_code">Этот QR код не является SimpleX-ccылкой.</string> + <string name="v5_5_private_notes_descr">С зашифрованными файлами и медиа.</string> + <string name="v5_5_message_delivery_descr">С уменьшенным потреблением батареи.</string> + <string name="keep_unused_invitation_question">Оставить неиспользованное приглашение?</string> + <string name="v5_5_message_delivery">Улучшенная доставка сообщений</string> + <string name="remote_ctrl_was_disconnected_title">Соединение остановлено</string> + <string name="restart_chat_button">Перезапустить чат</string> + <string name="start_chat_question">Запустить чат?</string> + <string name="note_folder_local_display_name">Личные заметки</string> + <string name="recent_history">Доступ к истории</string> + <string name="recent_history_is_not_sent_to_new_members">История не отправляется новым членам.</string> + <string name="recent_history_is_sent_to_new_members">До 100 последних сообщений отправляются новым членам.</string> + <string name="show_internal_errors">Показывать внутренние ошибки</string> + <string name="remote_ctrl_error_bad_state">Ошибка соединения с компьютером</string> + <string name="remote_host_error_bad_state"><![CDATA[Ошибка соединения с мобильным <b>%s</b>]]></string> + <string name="remote_ctrl_error_busy">Компьютер занят</string> + <string name="remote_ctrl_error_inactive">Компьютер неактивен</string> + <string name="remote_host_error_bad_version"><![CDATA[Версия приложения на мобильном <b>%s</b> не поддерживается. Пожалуйста, установите одинаковую версию на оба устройства.]]></string> + <string name="remote_host_error_busy"><![CDATA[Мобильный <b>%s</b> занят]]></string> + <string name="remote_host_error_disconnected"><![CDATA[Мобильный <b>%s</b> отсоединён]]></string> + <string name="remote_host_error_timeout"><![CDATA[Превышено максимальное время соединения с мобильным <b>%s</b>]]></string> + <string name="agent_critical_error_title">Критическая ошибка</string> + <string name="agent_critical_error_desc">Пожалуйста, сообщите об этом разработчикам: +\n%s +\n +\nРекомендовано перезапустить приложение.</string> + <string name="failed_to_create_user_invalid_title">Ошибка имени!</string> + <string name="failed_to_create_user_invalid_desc">Ошибка имени профиля. Пожалуйста, выберите другое имя.</string> + <string name="the_text_you_pasted_is_not_a_link">Вставленный текст не является SimpleX-ссылкой.</string> + <string name="creating_link">Создаётся ссылка…</string> + <string name="tap_to_paste_link">Нажмите, чтобы вставить ссылку</string> + <string name="invalid_qr_code">Ошибка QR кода</string> + <string name="share_this_1_time_link">Поделиться одноразовой ссылкой-приглашением</string> + <string name="retry_verb">Повторить</string> + <string name="app_was_crashed">Ошибка приложения</string> + <string name="error_showing_message">ошибка отображения сообщения</string> + <string name="error_showing_content">ошибка отображения содержания</string> + <string name="remote_ctrl_disconnected_with_reason">Отсоединён по причине: %s</string> + <string name="possible_deadlock_title">Взаимная блокировка</string> + <string name="possible_deadlock_desc">Выполнение задачи занимает долгое время: %1$d секунд. Возможно, приложение заблокировано: %2$s</string> + <string name="possible_slow_function_desc">Выполнение задачи занимает долгое время: %1$d секунд: %2$s</string> + <string name="possible_slow_function_title">Медленный вызов</string> + <string name="profile_update_event_contact_name_changed">контакт %1$s изменён на %2$s</string> + <string name="profile_update_event_member_name_changed">член %1$s изменился на %2$s</string> + <string name="profile_update_event_removed_address">удалён адрес контакта</string> + <string name="profile_update_event_removed_picture">удалена картинка профиля</string> + <string name="profile_update_event_set_new_address">установлен новый адрес контакта</string> + <string name="profile_update_event_set_new_picture">установлена новая картинка профиля</string> + <string name="profile_update_event_updated_profile">профиль обновлён</string> + <string name="remote_ctrl_error_bad_version">Версия приложения на компьютере не поддерживается. Пожалуйста, установите одинаковую версию на оба устройства.</string> + <string name="agent_internal_error_title">Внутренняя ошибка</string> + <string name="clear_note_folder_question">Очистить личные заметки?</string> + <string name="new_chat">Новый чат</string> + <string name="or_scan_qr_code">Или отсканируйте QR код</string> + <string name="you_can_view_invitation_link_again">Вы можете увидеть ссылку-приглашение снова открыв соединение.</string> + <string name="show_slow_api_calls">Показывать медленные вызовы API</string> + <string name="past_member_vName">Бывший член %1$s</string> + <string name="saved_message_title">Сохраненное сообщение</string> + <string name="group_member_status_unknown_short">неизвестно</string> + <string name="group_member_status_unknown">неизвестный статус</string> + <string name="blocked_by_admin_items_description">%d сообщений заблокировано администратором</string> + <string name="rcv_group_event_member_blocked">%s заблокирован</string> + <string name="rcv_group_event_member_unblocked">%s разблокирован</string> + <string name="snd_group_event_member_unblocked">Вы разблокировали %s</string> + <string name="unblock_for_all">Разблокировать для всех</string> + <string name="block_for_all_question">Заблокировать члена для всех?</string> + <string name="member_info_member_blocked">заблокирован</string> + <string name="blocked_by_admin_item_description">заблокировано администратором</string> + <string name="member_blocked_by_admin">Заблокирован администратором</string> + <string name="block_for_all">Заблокировать для всех</string> + <string name="error_blocking_member_for_all">Ошибка при блокировании члена для всех</string> + <string name="unblock_for_all_question">Разблокировать члена для всех?</string> + <string name="snd_group_event_member_blocked">Вы заблокировали %s</string> </resources> \ No newline at end of file diff --git a/apps/multiplatform/common/src/commonMain/resources/MR/th/strings.xml b/apps/multiplatform/common/src/commonMain/resources/MR/th/strings.xml index 91330717c4..5701c0ca78 100644 --- a/apps/multiplatform/common/src/commonMain/resources/MR/th/strings.xml +++ b/apps/multiplatform/common/src/commonMain/resources/MR/th/strings.xml @@ -112,8 +112,6 @@ <string name="both_you_and_your_contact_can_add_message_reactions">ทั้งคุณและผู้ติดต่อของคุณสามารถเพิ่มปฏิกิริยาต่อข้อความได้</string> <string name="both_you_and_your_contacts_can_delete">ทั้งคุณและผู้ติดต่อของคุณสามารถลบข้อความที่ส่งแล้วอย่างถาวรได้</string> <string name="use_camera_button">กล้อง</string> - <string name="add_new_contact_to_create_one_time_QR_code"><![CDATA[<b> เพิ่มผู้ติดต่อใหม่ </b>: เพื่อสร้างรหัส QR แบบใช้ครั้งเดียวสําหรับผู้ติดต่อของคุณ]]></string> - <string name="scan_QR_code_to_connect_to_contact_who_shows_QR_code"><![CDATA[<b>สแกนรหัส QR</b>: เพื่อเชื่อมต่อกับผู้ติดต่อที่แสดงรหัส QR ให้คุณ]]></string> <string name="learn_more_about_address">เกี่ยวกับที่อยู่ SimpleX</string> <string name="bold_text">ตัวหนา</string> <string name="callstatus_calling">กำลังโทร…</string> @@ -144,7 +142,6 @@ <string name="change_member_role_question">เปลี่ยนบทบาทกลุ่ม\?</string> <string name="icon_descr_cancel_live_message">ยกเลิกข้อความสด</string> <string name="feature_cancelled_item">ยกเลิกเรียบร้อยแล้ว %s</string> - <string name="cant_delete_user_profile">ไม่สามารถลบโปรไฟล์ผู้ใช้ได้!</string> <string name="alert_title_cant_invite_contacts">ไม่สามารถเชิญผู้ติดต่อได้!</string> <string name="change_verb">เปลี่ยน</string> <string name="change_database_passphrase_question">เปลี่ยนรหัสผ่านฐานข้อมูล\?</string> @@ -205,7 +202,6 @@ <string name="icon_descr_close_button">ปุ่มปิด</string> <string name="connect_button">เชื่อมต่อ</string> <string name="connect_via_link">เชื่อมต่อผ่านลิงก์</string> - <string name="create_one_time_link">สร้างลิงก์เชิญแบบใช้ครั้งเดียว</string> <string name="clear_verification">ล้างการยืนยัน</string> <string name="chat_console">คอนโซลแชท</string> <string name="smp_servers_check_address">ตรวจสอบที่อยู่เซิร์ฟเวอร์แล้วลองอีกครั้ง</string> @@ -1216,8 +1212,6 @@ <string name="updating_settings_will_reconnect_client_to_all_servers">การอัปเดตการตั้งค่าจะเชื่อมต่อไคลเอนต์กับเซิร์ฟเวอร์ทั้งหมดอีกครั้ง</string> <string name="user_unhide">ยกเลิกการซ่อน</string> <string name="user_unmute">เปิดเสียง</string> - <string name="should_be_at_least_one_profile">ควรมีโปรไฟล์ผู้ใช้อย่างน้อยหนึ่งโปรไฟล์</string> - <string name="should_be_at_least_one_visible_profile">ควรมีอย่างน้อยหนึ่งโปรไฟล์ผู้ใช้ที่มองเห็นได้</string> <string name="you_can_hide_or_mute_user_profile">คุณสามารถซ่อนหรือปิดเสียงโปรไฟล์ผู้ใช้ - กดค้างไว้เพื่อที่จะแสดงเมนู</string> <string name="unhide_profile">เลิกซ่อนโปรไฟล์</string> <string name="chat_preferences_you_allow">คุณอนุญาต</string> diff --git a/apps/multiplatform/common/src/commonMain/resources/MR/tr/strings.xml b/apps/multiplatform/common/src/commonMain/resources/MR/tr/strings.xml index ff9febd088..aa66835ee1 100644 --- a/apps/multiplatform/common/src/commonMain/resources/MR/tr/strings.xml +++ b/apps/multiplatform/common/src/commonMain/resources/MR/tr/strings.xml @@ -3,8 +3,7 @@ <string name="notifications">Bildirimler</string> <string name="connect_via_link_or_qr">Bağlantı ya da karekod ile bağlan</string> <string name="create_group">Gizli grup oluştur</string> - <string name="create_one_time_link">Tek seferlik davet bağlantısı oluştur</string> - <string name="your_simplex_contact_address">SimpleX addresin</string> + <string name="your_simplex_contact_address">SimpleX adresin</string> <string name="callstatus_missed">cevapsız çağrı</string> <string name="incoming_video_call">Gelen görüntülü arama</string> <string name="accept">Onayla</string> @@ -14,14 +13,14 @@ <string name="settings_audio_video_calls">Sesli ve görüntülü aramalar</string> <string name="icon_descr_video_call">Görüntülü ara</string> <string name="privacy_and_security">Gizlilik ve güvenlik</string> - <string name="incognito">Gizli ol</string> + <string name="incognito">Gizli</string> <string name="your_chats">Konuşmalar</string> <string name="connect_via_link">Bağlantı ile bağlan</string> - <string name="your_chat_profiles">Konuşma profillerin</string> + <string name="your_chat_profiles">Sohbet profillerin</string> <string name="chat_preferences">Konuşma tercihleri</string> <string name="network_and_servers">Ağ ve sunucular</string> <string name="appearance_settings">Görünüm</string> - <string name="your_settings">Ayarların</string> + <string name="your_settings">Ayarlarınız</string> <string name="mute_chat">Sessize al</string> <string name="unmute_chat">Sessizden çıkar</string> <string name="abort_switch_receiving_address_confirm">İptal</string> @@ -29,10 +28,10 @@ <string name="send_disappearing_message_30_seconds">30 saniye</string> <string name="send_disappearing_message_5_minutes">5 dakika</string> <string name="accept_contact_button">Onayla</string> - <string name="accept_connection_request__question">Bağlantı isteğini kabul et\?</string> - <string name="learn_more_about_address">SimpleX Adresiyle İlgili</string> - <string name="about_simplex_chat">SimpleX Chat İle İlgili</string> - <string name="about_simplex">SimpleX İle İlgili</string> + <string name="accept_connection_request__question">Bağlantı isteği kabul edilsin mi?</string> + <string name="learn_more_about_address">SimpleX Adresi Hakkında</string> + <string name="about_simplex_chat">SimpleX Chat Hakkında</string> + <string name="about_simplex">SimpleX Hakkında</string> <string name="accept_call_on_lock_screen">Yanıtla</string> <string name="abort_switch_receiving_address">Adres değişikliğini iptal et</string> <string name="notifications_mode_service">Sürekli açık</string> @@ -48,7 +47,7 @@ <string name="app_version_name">Uygulama sürümü: v%s</string> <string name="icon_descr_audio_call">sesli arama</string> <string name="audio_call_no_encryption">sesli arama (uçtan uca şifreli değil)</string> - <string name="answer_call">Aramaya cevap ver</string> + <string name="answer_call">Aramayı cevapla</string> <string name="full_backup">Uygulama veri yedekleme</string> <string name="all_app_data_will_be_cleared">Tüm uygulama verileri silinir.</string> <string name="settings_section_title_app">UYGULAMA</string> @@ -59,13 +58,13 @@ <string name="button_add_welcome_message">Karşılama mesajı ekleyin</string> <string name="users_delete_all_chats_deleted">Tüm konuşmalar ve mesajlar silinecektir. Bu, geri alınamaz!</string> <string name="color_primary">Ana renk</string> - <string name="chat_preferences_always">sürekli</string> + <string name="chat_preferences_always">her zaman</string> <string name="allow_message_reactions">Mesaj tepkilerine izin ver.</string> <string name="v4_3_improved_server_configuration_desc">Karekodu okutarak sunucular ekle.</string> <string name="v4_6_audio_video_calls">Sesli ve görüntülü aramalar</string> <string name="chat_item_ttl_day">1 gün</string> <string name="chat_item_ttl_month">1 ay</string> - <string name="add_address_to_your_profile">Profilinize adres ekleyin, böylece kişileriniz bunu diğer insanlarla paylaşabilir. Profil güncellemesi kişilerinize gönderilecektir.</string> + <string name="add_address_to_your_profile">Profilinize adres ekleyin, böylece kişileriniz adresinizi diğer insanlarla paylaşabilir. Profil güncellemesi kişilerinize gönderilecektir.</string> <string name="address_section_title">Adres</string> <string name="v4_2_group_links_desc">Yöneticiler, gruplara katılım bağlantısı oluşturabilirler.</string> <string name="all_group_members_will_remain_connected">Konuşma üyelerinin tümü bağlı kalacaktır.</string> @@ -90,7 +89,7 @@ <string name="save_servers_button">Kaydet</string> <string name="theme_colors_section_title">TEMA RENKLERİ</string> <string name="save_auto_accept_settings">Otomatik-kabul ayarlarını kaydet</string> - <string name="save_settings_question">Ayarları kaydet\?</string> + <string name="save_settings_question">Ayarlar kaydedilsin mi?</string> <string name="save_and_notify_contacts">Kaydet ve konuştuğun kişilere bildir</string> <string name="save_preferences_question">Tercihleri kaydet\?</string> <string name="save_profile_password">Profil parolasını kaydet</string> @@ -106,18 +105,16 @@ <string name="restore_database">Veri tabanı yedeğini geri yükle</string> <string name="restore_database_alert_title">Veri tabanı yedeğini geri yükle\?</string> <string name="database_restore_error">Veri tabanını geri yüklerken hata</string> - <string name="database_downgrade">Veri tabanının yapısal gerilemesi</string> + <string name="database_downgrade">Veritabanı sürüm düşürme</string> <string name="save_archive">Arşivi kaydet</string> <string name="current_version_timestamp">%s (mevcut)</string> <string name="save_and_update_group_profile">Kaydet ve grup profilini güncelle</string> - <string name="save_welcome_message_question">Karşılama mesajını kaydet\?</string> + <string name="save_welcome_message_question">Karşılama mesajı kaydedilsin mi?</string> <string name="network_options_reset_to_defaults">Varsayılana sıfırla</string> <string name="save_group_profile">Grup profilini kaydet</string> <string name="network_option_seconds_label">sn</string> <string name="network_options_save">Kaydet</string> - <string name="should_be_at_least_one_visible_profile">There should be at least one visible user profile.</string> - <string name="should_be_at_least_one_profile">En az bir kullanıcı profili olmalıdır.</string> - <string name="incognito_info_protects">Gizlilik kipi, ana profil adının ve görselinin gizliliğini korur. Tüm yeni kişiler için rastgele yeni bir profil oluşturulur.</string> + <string name="incognito_info_protects">Gizli mod her farklı kişi için yeni rasgele profil kullanarak gizliliğini korur.</string> <string name="theme_system">Sistem</string> <string name="language_system">Sistem</string> <string name="theme_light">Açık</string> @@ -137,7 +134,7 @@ <string name="custom_time_unit_seconds">saniye</string> <string name="save_verb">Kaydet</string> <string name="saved_ICE_servers_will_be_removed">Kaydedilen WebRTC ICE sunucuları kaldırılacaktır.</string> - <string name="smp_save_servers_question">Sunucuları kaydet\?</string> + <string name="smp_save_servers_question">Sunucular kaydedilsin mi?</string> <string name="save_passphrase_and_open_chat">Parolayı kaydet ve konuşmayı aç</string> <string name="save_and_notify_contact">Kaydet ve kişiyi bilgilendir</string> <string name="save_passphrase_in_keychain">Parolayı, Keystore\'a kaydet.</string> @@ -145,55 +142,55 @@ <string name="member_role_will_be_changed_with_notification">Yetki, \"%s\" olarak değiştirelecek. Gruptaki herkes bilgilendirilecek.</string> <string name="calls_prohibited_with_this_contact">Sesli/görüntülü aramalar yasaktır.</string> <string name="la_auth_failed">Kimlik doğrulama başarısız</string> - <string name="icon_descr_address">SimpleX adresi</string> + <string name="icon_descr_address">SimpleX Adresi</string> <string name="moderate_message_will_be_deleted_warning">Mesaj, tüm üyeler için silinecek.</string> <string name="the_messaging_and_app_platform_protecting_your_privacy_and_security">Gizliliğinizi ve güvenliğinizi koruyan mesajlaşma ve uygulama platformu.</string> <string name="settings_section_title_incognito">Gizlilik kipi</string> <string name="member_role_will_be_changed_with_invitation">Yetki, \"%s\" olarak değiştirilecek. Üye, yeni bir davet alacak.</string> <string name="role_in_group">Yetki</string> - <string name="allow_voice_messages_question">Sesli mesajlara izin ver\?</string> + <string name="allow_voice_messages_question">Sesli mesajlara izin verilsin mi?</string> <string name="users_add">Profil ekle</string> <string name="allow_direct_messages">Üyelere direkt mesaj gönderilmesine izin ver.</string> <string name="allow_to_send_disappearing">Kendiliğinden yok olan mesajlar göndermeye izin ver.</string> - <string name="allow_to_delete_messages">Gönderilen mesajların kalıcı olarak silinmesine izin ver.</string> + <string name="allow_to_delete_messages">Gönderilen mesajların kalıcı olarak silinmesine izin ver. (24 saat içinde)</string> <string name="allow_to_send_files">Dosya ve medya göndermeye izin ver.</string> <string name="allow_to_send_voice">Sesli mesaj göndermeye izin ver.</string> <string name="share_invitation_link">Tek kullanımlık bağlantıyı paylaş</string> - <string name="connect_via_invitation_link">Davet bağlantısı ile bağlan\?</string> - <string name="connect_via_group_link">Grup bağlantısı ile bağlan\?</string> - <string name="you_will_join_group">Bu bağlantının yönlendirdiği bir gruba katılacak ve üyeleriyle bağlantı kuracaksın.</string> + <string name="connect_via_invitation_link">Tek kullanımlık bağlantıyla bağlanılsın mı?</string> + <string name="connect_via_group_link">Gruba bağlan?</string> + <string name="you_will_join_group">Bütün grup üyelerine bağlanacaksın.</string> <string name="opening_database">Veri tabanı açılıyor…</string> <string name="server_connecting">bağlanılıyor</string> - <string name="moderated_item_description">%s yönetiyor</string> + <string name="moderated_item_description">%s tarafından yönetiliyor</string> <string name="sending_files_not_yet_supported">dosya gönderme henüz desteklenmiyor</string> <string name="unknown_message_format">bilinmeyen mesaj biçimi</string> <string name="invalid_message_format">geçersiz mesaj biçimi</string> <string name="live">CANLI</string> <string name="invalid_data">geçersiz veri</string> <string name="display_name_connection_established">bağlantı kuruldu</string> - <string name="display_name_invited_to_connect">bağlanmaya davet etti</string> + <string name="display_name_invited_to_connect">bağlanmaya davet edildi</string> <string name="display_name_connecting">bağlanılıyor…</string> <string name="description_you_shared_one_time_link">tek seferlik bağlantı paylaştınız</string> <string name="description_via_group_link">grup bağlantısı ile</string> - <string name="description_via_one_time_link">tek seferlik bağlantı ile</string> + <string name="description_via_one_time_link">tek seferlik bağlantı aracıığıyla</string> <string name="simplex_link_invitation">SimpleX tek kullanımlık bağlantı</string> <string name="simplex_link_group">SimpleX grup bağlantısı</string> <string name="simplex_link_mode">SimpleX bağlantıları</string> <string name="simplex_link_mode_description">Açıklama</string> - <string name="simplex_link_mode_full">Bütün olan bağlantı</string> + <string name="simplex_link_mode_full">Tam bağlantı</string> <string name="thousand_abbreviation">bin</string> <string name="profile_will_be_sent_to_contact_sending_link">Profiliniz, bu bağlantıyı aldığınız kişiye gönderilecek.</string> - <string name="connect_via_contact_link">Kişi bağlantısı üzerinden bağlan\?</string> + <string name="connect_via_contact_link">Adres bağlantısı üzerinden bağlan?</string> <string name="server_error">hata</string> <string name="connect_via_link_verb">Bağlan</string> <string name="server_connected">bağlanıldı</string> <string name="deleted_description">silindi</string> <string name="receiving_files_not_yet_supported">dosya alma henüz desteklenmiyor</string> <string name="sender_you_pronoun">sen</string> - <string name="invalid_chat">geçersiz konuşma</string> + <string name="invalid_chat">geçersi̇z sohbet</string> <string name="connection_local_display_name">bağlantı %1$d</string> <string name="simplex_link_mode_browser">Tarayıcı ile</string> - <string name="simplex_link_connection">%1$s ile</string> + <string name="simplex_link_connection">%1$s tarafından</string> <string name="connection_error">Bağlantı hatası</string> <string name="connection_timeout">Bağlantı süre aşımı</string> <string name="cannot_receive_file">Dosya alınamıyor</string> @@ -225,24 +222,24 @@ <string name="network_session_mode_entity">Bağlantı</string> <string name="network_session_mode_user">Konuşma profili</string> <string name="create_address">Adres oluştur</string> - <string name="callstatus_accepted">Yanıtlanmış arama</string> - <string name="callstatus_calling">aranıyor</string> + <string name="callstatus_accepted">kabul edilen arama</string> + <string name="callstatus_calling">aranıyor…</string> <string name="callstatus_in_progress">arama yapılıyor</string> <string name="colored_text">renklendirilmiş</string> <string name="confirm_password">Parolayı onayla</string> <string name="callstatus_rejected">geri çevrilmiş çağrı</string> <string name="create_profile_button">Oluştur</string> - <string name="callstatus_error">görüşme hatası</string> - <string name="callstate_connected">Bağlanıldı</string> + <string name="callstatus_error">arama hatası</string> + <string name="callstate_connected">bağlanıldı</string> <string name="callstate_connecting">bağlanılıyor…</string> <string name="call_already_ended">Görüşmesi çoktan bitti!</string> - <string name="your_calls">Görüşmelerin</string> + <string name="your_calls">Aramaların</string> <string name="open_verb">Aç</string> <string name="icon_descr_call_progress">Arama yapılıyor</string> <string name="icon_descr_call_rejected">Geri çevrilmiş çağrı</string> <string name="icon_descr_call_ended">Görüşme bitti.</string> - <string name="alert_text_decryption_error_too_many_skipped">%1$d mesaj atlanıldı.</string> - <string name="chat_database_deleted">Konuşma veri tabanı silindi</string> + <string name="alert_text_decryption_error_too_many_skipped">%1$d mesajlar atlanıldı.</string> + <string name="chat_database_deleted">Sohbet veritabanı silindi</string> <string name="error_with_info">Hata: %s</string> <string name="unknown_error">Bilinmeyen hata</string> <string name="rcv_group_event_member_connected">bağlanıldı</string> @@ -257,10 +254,10 @@ <string name="chat_preferences_yes">evet</string> <string name="accept_feature">Onayla</string> <string name="allow_disappearing_messages_only_if">Konuştuğun kişiler, kendiliğinden yok olan mesajlara izin veriyorsa sen de ver.</string> - <string name="allow_your_contacts_irreversibly_delete">Konuştuğun kişilerin gönderilen mesajları kalıcı olarak silmesine izin ver.</string> + <string name="allow_your_contacts_irreversibly_delete">Kişilerinin gönderilen mesajları kalıcı olarak silmesine izin ver. (24 saat içinde)</string> <string name="prohibit_sending_disappearing_messages">Kendiliğinden yok olan measj gönderimini engelle.</string> - <string name="allow_irreversible_message_deletion_only_if">Konuştuğun kişi, kalıcı olarak silinebilen mesajlara izin veriyorsa sen de ver.</string> - <string name="allow_message_reactions_only_if">Konuştuğun kişi, mesaj tepkilerine izin veriyorsa sen de ver.</string> + <string name="allow_irreversible_message_deletion_only_if">Konuştuğun kişi, kalıcı olarak silinebilen mesajlara izin veriyorsa sen de ver. (24 saat içinde)</string> + <string name="allow_message_reactions_only_if">Yalnızca kişin mesaj tepkilerine izin veriyorsa sen de ver.</string> <string name="only_you_can_send_disappearing">Sadece sen kendiliğinden yok olan mesaj gönderebilirsin.</string> <string name="only_your_contact_can_send_disappearing">Sadece konuştuğun kişi kendiliğinden yok olan mesaj gönderebilir.</string> <string name="both_you_and_your_contact_can_send_disappearing">Konuştuğun kişi de sen de kendiliğinden yok olan mesaj gönderebilirsiniz.</string> @@ -269,19 +266,19 @@ <string name="v4_4_disappearing_messages_desc">Gönderilen mesajlar, önceden belirlenmiş bir süre sonra silecektir.</string> <string name="v5_1_self_destruct_passcode_descr">Kullanıldığında bütün veriler silinir.</string> <string name="timed_messages">Kendiliğinden yok olan mesajlar</string> - <string name="allow_your_contacts_to_send_disappearing_messages">Konuştuğun kişilerin sana, kendiğinden yok olan mesajlar göndermesine izin ver.</string> + <string name="allow_your_contacts_to_send_disappearing_messages">Kişilerinin sana, kendiğinden yok olan mesajlar göndermesine izin ver.</string> <string name="disappearing_messages_are_prohibited">Bu grupta kendiliğinden yok olan mesajlara izin verilmiyor.</string> - <string name="alert_text_decryption_error_n_messages_failed_to_decrypt">%1$d mesaj deşifrelenemedi.</string> - <string name="group_info_section_title_num_members">%1$s ÜYE</string> - <string name="integrity_msg_skipped">%1$d atlanılmış mesaj</string> - <string name="allow_calls_only_if">Konuştuğun kişi, aramalara izin veriyorsa sen de ver.</string> + <string name="alert_text_decryption_error_n_messages_failed_to_decrypt">%1$d mesajlar deşifrelenemedi.</string> + <string name="group_info_section_title_num_members">%1$s ÜYELER</string> + <string name="integrity_msg_skipped">%1$d atlanılmış mesaj(lar)</string> + <string name="allow_calls_only_if">Yalnızca irtibat kişiniz izin veriyorsa aramalara izin verin.</string> <string name="allow_your_contacts_adding_message_reactions">Konuştuğun kişilerin mesajlarına tepki eklemesine izin ver.</string> - <string name="allow_your_contacts_to_call">Konuştuğun kişilerin seni aramasına izin ver.</string> - <string name="all_your_contacts_will_remain_connected">Konuştuğun kişilerin tümü bağlı kalacaktır.</string> + <string name="allow_your_contacts_to_call">Kişilerinin seni aramasına izin ver.</string> + <string name="all_your_contacts_will_remain_connected">Kişilerin tümü bağlı kalacaktır.</string> <string name="icon_descr_cancel_file_preview">Dosya ön izlemesini iptal et</string> - <string name="chat_database_imported">Konuşma veri tabanı içe aktarıldı</string> + <string name="chat_database_imported">Sohbet veritabanı içe aktarıldı</string> <string name="icon_descr_cancel_image_preview">Görsel ön izlemesini iptal et</string> - <string name="clear_chat_question">Konuşmayı temizle\?</string> + <string name="clear_chat_question">Konuşma temizlensin mi?</string> <string name="v4_6_chinese_spanish_interface">Çince ve İspanyolca arayüz</string> <string name="confirm_new_passphrase">Yeni parolayı onayla…</string> <string name="info_row_connection">Bağlantı</string> @@ -296,25 +293,25 @@ <string name="settings_section_title_calls">ARAMALAR</string> <string name="settings_section_title_chats">KONUŞMALAR</string> <string name="settings_section_title_you">SEN</string> - <string name="chat_database_section">KONUŞMA VERİ TABANI</string> + <string name="chat_database_section">SOHBET VERİTABANI</string> <string name="remove_passphrase">Kaldır</string> <string name="wrong_passphrase_title">Yanlış parola!</string> - <string name="confirm_database_upgrades">Veri tabanının yapısal ilerlemelerini onayla</string> + <string name="confirm_database_upgrades">Veritabanı yükseltmelerini onayla</string> <string name="rcv_group_event_member_deleted">%1$s çıkarıldı</string> <string name="rcv_group_event_user_deleted">seni çıkardı</string> <string name="group_member_status_connected">bağlanıldı</string> - <string name="group_member_status_announced">bağlanılıyor (duyruldu)</string> + <string name="group_member_status_announced">bağlanılıyor (duyuruldu)</string> <string name="group_info_member_you">sen: %1$s</string> - <string name="group_member_status_removed">çıkarıldı</string> + <string name="group_member_status_removed">kaldırıldı</string> <string name="member_info_section_title_member">ÜYE</string> <string name="group_members_can_send_disappearing">Grup üyeleri kendiliğinden yok olan mesajlar gönderebilir.</string> <string name="prohibit_sending_disappearing">Kendiliğinden yok olan mesaj gönderimini engelle.</string> - <string name="allow_voice_messages_only_if">Konuştuğun kişi, sesli mesajlara izin veriyorsa sen de ver.</string> - <string name="allow_your_contacts_to_send_voice_messages">Konuştuğun kişilerin sesli mesaj göndermesine izin ver.</string> + <string name="allow_voice_messages_only_if">Yalnızca kişiniz sesli mesaj göndermeye izin veriyorsa sen de ver.</string> + <string name="allow_your_contacts_to_send_voice_messages">Kişilerinin sesli mesaj göndermesine izin ver.</string> <string name="both_you_and_your_contact_can_add_message_reactions">Konuştuğun kişi de sen de mesajlara tepki ekleyebilirsinsiz.</string> <string name="both_you_and_your_contact_can_send_voice">Konuştuğun kişi de sen de sesli mesaj gönderebilirsiniz.</string> <string name="v4_4_disappearing_messages">Kendiliğinden yok olan mesajlar</string> - <string name="both_you_and_your_contacts_can_delete">Konuştuğun kişi de sen de mesajları kalıcı olarak silebilirsiniz.</string> + <string name="both_you_and_your_contacts_can_delete">Konuştuğun kişi ve sen mesajları kalıcı olarak silebilirsiniz. (24 saat içinde)</string> <string name="decryption_error">Deşifreleme hatası</string> <string name="description_via_contact_address_link">kişi adres bağlantısı ile</string> <string name="simplex_link_contact">SimpleX bağlantı adresi</string> @@ -342,9 +339,9 @@ <string name="error_creating_link_for_group">Toplu konuşma bağlantısı oluştururken hata oluştu</string> <string name="error_changing_role">Yetki değiştirirken hata oluştu</string> <string name="error_deleting_link_for_group">Toplu konuşma bağlantısı silinirken hata oluştu</string> - <string name="error_deleting_contact">Konuştuğun kişiyi silerken hata oluştu</string> + <string name="error_deleting_contact">Kişiyi silerken hata oluştu</string> <string name="error_deleting_contact_request">Konuşma isteği silinirken hata oluştu</string> - <string name="error_deleting_group">Toplu konuşma silinirken hata oluştu</string> + <string name="error_deleting_group">Grup silinirken hata oluştu</string> <string name="error_deleting_pending_contact_connection">Bekleyen konuşma bağlantısını silinirken hata oluştu</string> <string name="error_deleting_user">Kullanıcı profili silinirken hata oluştu</string> <string name="error_deleting_database">Konuşma veri tabanı silinirken hata oluştu</string> @@ -356,15 +353,15 @@ <string name="error_importing_database">Konuşma veri tabanını içe aktarılırken hata oluştu</string> <string name="database_error">Veri tabanı hatası</string> <string name="create_your_profile">Profilini oluştur</string> - <string name="custom_time_picker_custom">kişiselleştirilmiş</string> + <string name="custom_time_picker_custom">özel</string> <string name="database_passphrase_will_be_updated">Veri tabanının şifrelemesinde kullanılan parolası güncellenecek.</string> <string name="encrypted_with_random_passphrase">Veri tabanı, rastgele bir parola ile şifrelendi. İstersen parolayı değiştirebilirsin.</string> <string name="ttl_d">%dg</string> - <string name="delete_link_question">Bağlantıyı sil\?</string> + <string name="delete_link_question">Bağlantı silinsin mi?</string> <string name="ttl_hours">%d saat</string> <string name="v4_6_group_moderation_descr">Yeni yöneticiler artık: \n- üyelerin mesajlarını silebilir. -\n- üyeleri etkisizleştirebilir (\"gözlemci\" yetkisi)</string> +\n- üyeleri etkisizleştirebilir (\"gözlemci\" yetkisi verir)</string> <string name="receipts_section_contacts">Konuşmalar</string> <string name="create_group_link">Grup bağlantısı oluştur</string> <string name="error_accepting_contact_request">Konuşma isteğini onaylarken hata oluştu</string> @@ -378,8 +375,8 @@ <string name="la_current_app_passcode">Güncel Erişim Kodu</string> <string name="copy_verb">Kopyala</string> <string name="delete_verb">Sil</string> - <string name="delete_message__question">Mesajı sil\?</string> - <string name="delete_member_message__question">Üye mesajını sil\?</string> + <string name="delete_message__question">Mesaj silinsin mi?</string> + <string name="delete_member_message__question">Üyenin mesajı silinsin mi?</string> <string name="for_me_only">Benim için sil</string> <string name="icon_descr_context">İçerik simgesi</string> <string name="image_decoding_exception_title">Dekodlama hatası</string> @@ -407,10 +404,10 @@ <string name="delete_image">Görseli sil</string> <string name="you_control_your_chat">Konuşman, senin elinde!</string> <string name="create_profile">Profil oluştur</string> - <string name="decentralized">Özeksiz</string> + <string name="decentralized">Merkezi olmayan</string> <string name="confirm_passcode">Erişim kodunu onayla</string> <string name="incorrect_passcode">Yanlış erişim kodu</string> - <string name="new_passcode">Yeni Şifre</string> + <string name="new_passcode">Yeni erişim kodu</string> <string name="submit_passcode">Gönder</string> <string name="la_mode_passcode">Erişim kodu</string> <string name="passcode_changed">Erişim kodu değişti!</string> @@ -443,7 +440,7 @@ <string name="group_member_status_creator">oluşturan</string> <string name="no_contacts_selected">Hiçbir konuşma seçilmedi</string> <string name="num_contacts_selected">%d tane konuşma seçildi</string> - <string name="share_text_database_id">Veri tabanı kimliği: %d</string> + <string name="share_text_database_id">Veritabanı kimliği: %d</string> <string name="info_row_deleted_at">Şu tarihte silindi</string> <string name="share_text_deleted_at">Şu tarihte silindi: %s</string> <string name="item_info_current">(güncel)</string> @@ -460,24 +457,24 @@ <string name="database_encrypted">Veri tabanı şifrelendi!</string> <string name="delete_messages">Mesajları sil</string> <string name="delete_messages_after">Şu süre sonra mesajları sil</string> - <string name="total_files_count_and_size">%d tane dosya, toplam boyutu %s</string> + <string name="total_files_count_and_size">%d dosya(lar),toplam boyut olarak %s</string> <string name="new_passphrase">Yeni parola…</string> <string name="database_will_be_encrypted_and_passphrase_stored">Veri tabanı şifrelenecek ve parola, Keystore\'a kaydedilecek.</string> <string name="database_encryption_will_be_updated">Veri tabanının şifrelemesinde kullanılan parola güncellenecek ve Keystore\'da barındıralacak.</string> <string name="passphrase_is_different">Veri tabanı parolası, Keystore\'da barındırılandan değişik.</string> <string name="database_passphrase_is_required">Konuşmayı açmak için veri tabanı parolası gerekli.</string> - <string name="database_upgrade">Veri tabanını yapısal olarak ilerlet</string> + <string name="database_upgrade">Veritabanı yükseltmesi</string> <string name="rcv_group_event_changed_your_role">yetkin, %s olarak değişti</string> <string name="snd_group_event_changed_member_role">%s üyesinin yetkisini, %s olarak değiştirdin</string> - <string name="group_member_role_owner">iye/sahip</string> + <string name="group_member_role_owner">sahip</string> <string name="icon_descr_expand_role">Yetki seçimini genişlet</string> <string name="initial_member_role">İlk olarak verilen yetki</string> <string name="new_member_role">Yeni üye yetkisi</string> <string name="button_delete_group">Grubu sil</string> - <string name="delete_group_question">Grubu sil\?</string> + <string name="delete_group_question">Grup silinsin mi?</string> <string name="button_create_group_link">Bağlantı oluştur</string> <string name="delete_link">Bağlantıyı sil</string> - <string name="info_row_database_id">Veri tabanı kimliği</string> + <string name="info_row_database_id">Veritabanı kimliği</string> <string name="change_role">Yetkiyi değiştir</string> <string name="create_secret_group_title">Gizli grup oluştur</string> <string name="chat_preferences_no">hayır</string> @@ -502,18 +499,18 @@ <string name="edit_image">Görseli düzenle</string> <string name="encrypted_audio_call">uçtan uca şifreli sesli arama</string> <string name="encrypted_video_call">uçtan uca şifreli görüntülü arama</string> - <string name="status_e2e_encrypted">uçtan uca şifreli</string> + <string name="status_e2e_encrypted">uçtan uca şifrelenmiş</string> <string name="allow_accepting_calls_from_lock_screen">Ayarlardan, kilitli ekrandan aramaları izin ver.</string> - <string name="integrity_msg_duplicate">Aynısı bulunan mesaj</string> + <string name="integrity_msg_duplicate">yinelenen mesaj</string> <string name="enable_lock">Kilidi etkinleştir</string> <string name="info_row_disappears_at">Kendiliğinden şu sürede yok olacak</string> <string name="share_text_disappears_at">Kendiliğinden şu sürede yok olacak: %s</string> - <string name="feature_enabled">etkinleşti</string> + <string name="feature_enabled">etkin</string> <string name="direct_messages">Direkt mesaj</string> <string name="no_call_on_lock_screen">Devre dışı bırak</string> <string name="display_name_cannot_contain_whitespace">Görünen ad, boşluk gibi aralıklama türleri içeremez.</string> - <string name="display_name">Görünen Ad</string> - <string name="display_name__field">Görünen ad:</string> + <string name="display_name">İsmini gir:</string> + <string name="display_name__field">Profil adı:</string> <string name="ttl_mth">%day</string> <string name="ttl_s">%dsn</string> <string name="dont_create_address">Adres oluşturma</string> @@ -524,18 +521,18 @@ <string name="receipts_contacts_disable_for_all">Herkes için devre dışı bırak</string> <string name="receipts_contacts_disable_keep_overrides">Devre dışı bırak (ayrıcalıklar kalsın)</string> <string name="receipts_contacts_enable_for_all">tüm kişiler için etkinleştir</string> - <string name="enable_automatic_deletion_question">Kendi kendine silinen mesajları etkinleştir\?</string> + <string name="enable_automatic_deletion_question">Kendi kendine silinen mesajlar etkinleştirilsin mi?</string> <string name="encrypt_database">Şifrele</string> <string name="encrypt_database_question">Veri tabanını şifrele\?</string> <string name="conn_event_ratchet_sync_ok">şifreleme etkin</string> <string name="button_edit_group_profile">Toplu konuşma profilini düzenle</string> <string name="conn_event_ratchet_sync_agreed">şifreleme kabul edildi</string> <string name="snd_conn_event_ratchet_sync_agreed">%s üyesi için şifreleme kabul edildi</string> - <string name="conn_level_desc_direct">direkt</string> + <string name="conn_level_desc_direct">doğrudan</string> <string name="dont_show_again">Yeniden gösterme</string> <string name="direct_messages_are_prohibited_in_chat">Bu grupta üyeler arası direkt mesajlar yasaklıdır.</string> <string name="feature_enabled_for_contact">konuşulan kişi için etkinleşti</string> - <string name="feature_enabled_for_you">senin için etkinleşti</string> + <string name="feature_enabled_for_you">senin için etkinleştirildi</string> <string name="ttl_sec">%d sn</string> <string name="ttl_m">%da</string> <string name="ttl_min">%d dk</string> @@ -585,11 +582,11 @@ <string name="incorrect_code">Yanlış güvenlik kodu!</string> <string name="how_to_use_your_servers">Sunucuların nasıl kullanılır</string> <string name="enter_one_ICE_server_per_line">ICE sunucuları (her satır başı bir tane)</string> - <string name="host_verb">Barındır</string> + <string name="host_verb">Ana bilgisayar</string> <string name="hide_dev_options">Gizle:</string> <string name="full_name__field">Ad ve soyad:</string> <string name="email_invite_body">Merhaba! -\nSimplex Chat kullanarak benle bağlantıya geç: %s</string> +\nSimplex Chat kullanarak benimle bağlantıya geç: %s</string> <string name="exit_without_saving">Kaydetmeden çık</string> <string name="hide_profile">Profili gizle</string> <string name="error_saving_user_password">Kullanıcı parolası kaydedilirken hata oluştu</string> @@ -599,7 +596,7 @@ <string name="immune_to_spam_and_abuse">Kötüye kullanmaya ve istenmeyen mesajlara duyarlı</string> <string name="icon_descr_hang_up">Çağırıyı bitir.</string> <string name="icon_descr_flip_camera">Kameranın karşı yüzüne geç</string> - <string name="import_database_question">Konuşma veri tabanını içe aktar\?</string> + <string name="import_database_question">Konuşma veri tabanı içe aktarılsın mı?</string> <string name="alert_message_group_invitation_expired">Grup daveti artık geçerli değil. Gönderici tarafından kaldırıldı.</string> <string name="alert_title_no_group">Grup bulunamadı!</string> <string name="delete_group_for_all_members_cannot_undo_warning">Grup tüm üyeler için silinecektir - bu geri alınamaz!</string> @@ -641,23 +638,23 @@ <string name="incompatible_database_version">Uyumsuz veri tabanı sürümü</string> <string name="icon_descr_group_inactive">Grup etkin değil</string> <string name="group_invitation_expired">Grup davetinin süresi doldu</string> - <string name="snd_group_event_group_profile_updated">Grup profili güncellendi</string> - <string name="group_member_status_group_deleted">toplu konuşma silindi</string> + <string name="snd_group_event_group_profile_updated">grup profili güncellendi</string> + <string name="group_member_status_group_deleted">grup silindi</string> <string name="error_updating_link_for_group">Toplu konuşma bağlantısı güncellenirken hata oluştu</string> <string name="section_title_for_console">UÇBİRİM İÇİN</string> <string name="group_link">Grup bağlantısı</string> - <string name="info_row_group">Toplu konuşma</string> + <string name="info_row_group">Grup</string> <string name="conn_level_desc_indirect">dolaylı (%1$s)</string> <string name="fix_connection">Bağlantıyı onar</string> - <string name="fix_connection_question">Bağlantıyı onar\?</string> + <string name="fix_connection_question">Bağlantı onarılsın mı?</string> <string name="fix_connection_confirm">Onar</string> <string name="fix_connection_not_supported_by_contact">Konuştuğunuz kişi, onarımı desteklemiyor.</string> <string name="fix_connection_not_supported_by_group_member">Toplu konuşma üyesi, onarımı desteklemiyor.</string> - <string name="group_display_name_field">Grup görünen adı:</string> + <string name="group_display_name_field">Grup adını gir:</string> <string name="group_full_name_field">Grup tam adı:</string> <string name="files_and_media">Dosya ve medya</string> <string name="group_members_can_send_dms">Grup üyeleri direkt mesaj gönderebilir.</string> - <string name="group_members_can_delete">Gru üyeleri, gönderilen mesajları kalıcı olarak silebilir.</string> + <string name="group_members_can_delete">Grup üyeleri, gönderilen mesajları kalıcı olarak silebilir. (24 saat içinde)</string> <string name="group_members_can_send_voice">Grup üyeleri sesli mesaj gönderebilirler.</string> <string name="files_are_prohibited_in_group">Bu toplu konuşmada, dosya ve medya yasaklanmıştır.</string> <string name="group_members_can_send_files">Grup üyeleri dosya ve medya paylaşabilir.</string> @@ -670,7 +667,7 @@ <string name="v4_6_group_moderation">Grup yönetimi</string> <string name="v4_6_group_welcome_message">Grup karşılama mesajı</string> <string name="v4_6_hidden_chat_profiles">Gizli konuşma profilleri</string> - <string name="custom_time_unit_hours">Saat</string> + <string name="custom_time_unit_hours">saat</string> <string name="notifications_mode_off_desc">Sadece uygulama çalışırken bildirim alabileceksiniz, hiçbir arka plan hizmeti başlatılmayacaktır</string> <string name="notification_preview_new_message">yeni mesaj</string> <string name="welcome">Hoşgeldin!</string> @@ -694,7 +691,7 @@ <string name="empty_chat_profile_is_created">Verilen adla boş bir sohbet profili oluşturulur ve uygulama her zamanki gibi açılır.</string> <string name="voice_prohibited_in_this_chat">Bu sohbette sesli mesajlar yasaktır.</string> <string name="v4_2_auto_accept_contact_requests">Bağlanma isteklerini otomatik kabul et</string> - <string name="database_downgrade_warning">Uyarı: Bazı verileri kaybedebilirsiniz!</string> + <string name="database_downgrade_warning">Uyarı: Bazı verileri kaybedebilirsin!</string> <string name="all_your_contacts_will_remain_connected_update_sent">Tüm kişileriniz bağlı kalacaktır. Profil güncellemesi kişilerinize gönderilecektir.</string> <string name="keychain_is_storing_securely">Android Keystore parolayı güvenli bir şekilde saklamak için kullanılır - bildirim hizmetinin çalışmasını sağlar.</string> <string name="button_welcome_message">Karşılama mesajı</string> @@ -713,7 +710,7 @@ <string name="icon_descr_instant_notifications">Anlık bildirimler</string> <string name="service_notifications">Anlık bildirimler</string> <string name="service_notifications_disabled">Anlık bildirimler devre dışı!</string> - <string name="turn_off_battery_optimization"><![CDATA[Bunu kullanmak için lütfen bir sonraki iletişim kutusunda SimpleX için <b>pil optimizasyonunu devre dışı bırakın</b>. Aksi takdirde, bildirimler devre dışı bırakılacaktır.]]></string> + <string name="turn_off_battery_optimization"><![CDATA[Kullanmak için, lütfen bir sonraki iletişim kutusunda <b>SimpleX in arkaplanda çalışmasına izin ver</b> seçeneğini işaretleyin. Aksi takdirde, bildirimler devre dışı bırakılacaktır.]]></string> <string name="notification_preview_mode_contact">Kişi ismi</string> <string name="auth_device_authentication_is_disabled_turning_off">Cihaz doğrulaması devre dışı. SimpleX Kilidi Kapatılıyor.</string> <string name="auth_device_authentication_is_not_enabled_you_can_turn_on_in_settings_once_enabled">Cihaz doğrulaması etkin değil. Cihaz doğrulamasını etkinleştirdikten sonra SimpleX Kilidini Ayarlar üzerinden açabilirsiniz.</string> @@ -736,13 +733,12 @@ <string name="v4_3_irreversible_message_deletion">Geri alınamaz mesaj silme</string> <string name="v4_5_italian_interface">İtalyanca arayüz</string> <string name="choose_file_title">Dosya seç</string> - <string name="scan_QR_code_to_connect_to_contact_who_shows_QR_code"><![CDATA[<b>QR kodunu tara</b>: size QR kodunu gösteren kişiyle bağlantı kurmak için.]]></string> <string name="invite_friends">Arkadaşlarınızı davet edin</string> <string name="bold_text">kalın</string> - <string name="italic_text">İtalik</string> + <string name="italic_text">italik</string> <string name="onboarding_notifications_mode_subtitle">Daha sonra ayarlardan değiştirebilirsiniz.</string> - <string name="status_contact_has_e2e_encryption">Kişi uçtan uca şifrelemeye sahiptir</string> - <string name="status_contact_has_no_e2e_encryption">Kişi uçtan uca şifrelemeye sahip değildir</string> + <string name="status_contact_has_e2e_encryption">kişi uçtan uca şifrelemeye sahiptir</string> + <string name="status_contact_has_no_e2e_encryption">kişi uçtan uca şifrelemeye sahip değildir</string> <string name="chat_is_stopped">Sohbet durduruldu</string> <string name="impossible_to_recover_passphrase"><![CDATA[<b>Aklınızda bulunsun</b>: kaybederseniz, parolayı kurtaramaz veya değiştiremezsiniz.]]></string> <string name="chat_archive_header">Sohbet arşivi</string> @@ -755,12 +751,11 @@ <string name="invite_to_group_button">Gruba davet edin</string> <string name="invite_prohibited">Kişi davet edilemiyor!</string> <string name="button_add_members">Üyeleri davet edin</string> - <string name="cant_delete_user_profile">Kullanıcı profili silinemiyor!</string> <string name="color_background">Arka plan</string> <string name="message_deletion_prohibited">Bu sohbette geri alınamaz mesaj silme yasaktır.</string> <string name="delete_contact_question">Kişiyi sil\?</string> <string name="button_delete_contact">Kişiyi sil</string> - <string name="callstatus_connecting">Aramaya bağlanılıyor…</string> + <string name="callstatus_connecting">aramaya bağlanılıyor…</string> <string name="delivery_receipts_are_disabled">Gönderildi bilgisi kapalı!</string> <string name="v5_2_more_things">Birkaç şey daha</string> <string name="onboarding_notifications_mode_service_desc"><![CDATA[<b>Daha fazla pil kullanır</b>! Arka plan hizmeti her zaman çalışır - mesajlar gelir gelmez bildirim gönderilir.]]></string> @@ -775,9 +770,9 @@ <string name="delivery_receipts_title">Mesaj gönderildi bilgisi!</string> <string name="joining_group">Gruba katılınıyor</string> <string name="description_you_shared_one_time_link_incognito">tek seferlik gizli bağlantı paylaştınız</string> - <string name="description_via_group_link_incognito">Grup bağlantısı ile gizli</string> - <string name="description_via_contact_address_link_incognito">Bağlantı linki ile gizli</string> - <string name="description_via_one_time_link_incognito">Tek seferlik bağlantı ile gizli</string> + <string name="description_via_group_link_incognito">grup bağlantısı ile gizli</string> + <string name="description_via_contact_address_link_incognito">kişi bağlantı linki ile gizli</string> + <string name="description_via_one_time_link_incognito">tek seferlik bağlantı aracılığıyla gizli</string> <string name="smp_server_test_compare_file">Dosyaları karşılaştır</string> <string name="it_can_disabled_via_settings_notifications_still_shown"><![CDATA[<b>ayarlardan devre dışı bırakılabilir</b> - uygulama çalışıyorken bildirimler gösterilmeye devam edilecektir.]]></string> <string name="turning_off_service_and_periodic">Pil optimizasyonu etkin, arka plan hizmeti kapatılacak ve düzenli olarak yeni mesajlar kontrol edilmeyecek . Bunları ayarlardan yeniden etkinleştirebilirsiniz.</string> @@ -788,9 +783,8 @@ <string name="auth_unavailable">Doğrulama mevcut değil</string> <string name="message_delivery_error_title">Mesaj teslim hatası</string> <string name="delete_message_cannot_be_undone_warning">Mesajlar silinecek - bu geri alınamaz!</string> - <string name="switch_receiving_address_question">Alıcı adresini değiştir\?</string> + <string name="switch_receiving_address_question">Alıcı adresi değiştirilsin mi?</string> <string name="back">Geri</string> - <string name="add_new_contact_to_create_one_time_QR_code"><![CDATA[<b>Yeni kişi ekle</b>: Kişiniz için tek seferlik QR Kodunuzu oluşturmak için.]]></string> <string name="you_will_be_connected_when_your_connection_request_is_accepted">Bağlantı isteğiniz kabul edildiğinde bağlanacaksınız, lütfen bekleyin veya daha sonra kontrol edin!</string> <string name="you_will_be_connected_when_your_contacts_device_is_online">Kişinizin cihazı çevrimiçi olduğunda bağlanacaksınız, lütfen bekleyin veya daha sonra kontrol edin!</string> <string name="learn_more">Daha fazla bilgi edinin</string> @@ -812,7 +806,7 @@ \nv5.1\'de mevcut"</string> <string name="v4_5_transport_isolation_descr">Sohbet profili ile (varsayılan) veya bağlantı ile (BETA).</string> <string name="image_descr_link_preview">bağlantı önizleme resmi</string> - <string name="your_profile_is_stored_on_your_device">Profiliniz, kişileriniz ve mesajlar cihazınızda saklanır.</string> + <string name="your_profile_is_stored_on_your_device">Profiliniz, kişileriniz ve gönderilmiş mesajlar cihazınızda saklanır.</string> <string name="callstatus_ended">arama sona erdi %1$s</string> <string name="call_on_lock_screen">Kilit ekranında aramalar:</string> <string name="alert_title_msg_bad_id">Kötü mesaj kimliği</string> @@ -824,7 +818,7 @@ <string name="snd_conn_event_switch_queue_phase_changing">adres değiştiriliyor…</string> <string name="group_member_status_left">ayrıldı</string> <string name="button_leave_group">Gruptan ayrıl</string> - <string name="incognito_random_profile">Rastgele profiliniz</string> + <string name="incognito_random_profile">Rasgele profiliniz</string> <string name="message_reactions_prohibited_in_this_chat">Mesaj tepkileri bu sohbette yasaklıdır</string> <string name="v5_1_message_reactions">Mesaj tepkileri</string> <string name="v5_1_better_messages">Daha iyi mesajlar</string> @@ -851,13 +845,13 @@ <string name="your_preferences">Tercihleriniz</string> <string name="message_reactions_are_prohibited">Mesaj tepkileri bu grupta yasaklıdır</string> <string name="connected_to_server_to_receive_messages_from_contact">Bu kişiden mesaj almak için kullanılan sunucuya bağlısınız.</string> - <string name="you_are_already_connected_to_vName_via_this_link">Zaten şuna bağlısınız: %1$s</string> + <string name="you_are_already_connected_to_vName_via_this_link">Zaten %1$s e bağlısınız</string> <string name="la_could_not_be_verified">Doğrulanamadınız; lütfen tekrar deneyin.</string> <string name="you_can_turn_on_lock">SimpleX Kilidini Ayarlar üzerinden açabilirsiniz.</string> <string name="group_preview_you_are_invited">gruba davet edildiniz</string> <string name="you_have_no_chats">Hiç sohbetiniz yok</string> <string name="you_are_observer">Gözlemcisiniz</string> - <string name="observer_cant_send_message_title">Mesaj gönderemezsiniz</string> + <string name="observer_cant_send_message_title">Mesajlar gönderemezsiniz!</string> <string name="view_security_code">Güvenlik kodunu görüntüle</string> <string name="you_need_to_allow_to_send_voice">Sesli mesaj gönderebilmeniz için kişinizin de sesli mesaj göndermesine izin vermeniz gerekir.</string> <string name="xftp_servers">XFTP sunucuları</string> @@ -877,9 +871,9 @@ <string name="your_contacts_will_remain_connected">Kişileriniz bağlı kalacaktır.</string> <string name="you_can_create_it_later">Daha sonra oluşturabilirsiniz</string> <string name="you_can_use_markdown_to_format_messages__prompt">Mesajları biçimlendirmek için markdown kullanabilirsiniz:</string> - <string name="your_chat_database">Mesaj veri tabanınız</string> + <string name="your_chat_database">Sohbet veritabanınız</string> <string name="your_current_chat_database_will_be_deleted_and_replaced_with_the_imported_one">Mevcut sohbet veritabanınız SİLİNECEK ve içe aktarılan veritabanıyla DEĞİŞTİRİLECEKTİR. -\nBu işlem geri alınamaz - profiliniz, kişileriniz, mesajlarınız ve dosyalarınız geri alınamaz şekilde kaybolacaktır.</string> +\nBu eylem geri alınamaz - profiliniz, kişileriniz, mesajlarınız ve dosyalarınız geri alınamaz şekilde kaybolacaktır.</string> <string name="youve_accepted_group_invitation_connecting_to_inviting_group_member">Bu gruba katıldınız. Davet eden grup üyesine bağlanılıyor.</string> <string name="you_are_invited_to_group_join_to_connect_with_group_members">Gruba davetlisiniz. Grup üyeleriyle bağlantı kurmak için katılın.</string> <string name="alert_title_cant_invite_contacts_descr">Bu grup için gizli bir profil kullanıyorsunuz - ana profilinizi paylaşmayı önlemek için kişileri davet etmeye izin verilmiyor</string> @@ -896,13 +890,13 @@ <string name="you_can_share_your_address">Adresinizi bir bağlantı veya QR kodu olarak paylaşabilirsiniz - herkes size bağlanabilir.</string> <string name="snd_conn_event_switch_queue_phase_completed">bağlantı değiştirdiniz</string> <string name="you_can_enable_delivery_receipts_later">Daha sonra Ayarlardan etkinleştirebilirsin</string> - <string name="you_can_enable_delivery_receipts_later_alert">Sonrasında uygulamanın Gizlilik ve Güvenlik ayarlarından etkinleştirebilirsiniz.</string> + <string name="you_can_enable_delivery_receipts_later_alert">Daha sonra uygulamanın Gizlilik ve Güvenlik ayarlarından etkinleştirebilirsiniz.</string> <string name="alert_text_connection_pending_they_need_to_be_online_can_delete_and_retry">Bağlantının tamamlanması için kişinizin çevrimiçi olması gerekir. \nBu bağlantıyı iptal edebilir ve kişiyi kaldırabilirsiniz (ve daha sonra yeni bir bağlantıyla deneyebilirsiniz).</string> <string name="contact_sent_large_file">Kişiniz desteklenen maksimum boyuttan (%1$s) daha büyük bir dosya gönderdi.</string> <string name="video_will_be_received_when_contact_completes_uploading">Kişiniz yüklemeyi tamamladığında video alınacaktır.</string> <string name="you_can_also_connect_by_clicking_the_link"><![CDATA[Ayrıca bağlantıya tıklayarak da bağlanabilirsiniz. Eğer bağlantı tarayıcda açılırsa, <b>mobil uygulamada aç</b> seçeneğine tıklayın.]]></string> - <string name="you_can_connect_to_simplex_chat_founder"><![CDATA[Soru sormak ve güncellemeleri almak için <font color=#0088ff>SimpleX Chat geliştiricilerine bağlanabilirsiniz</font>.]]></string> + <string name="you_can_connect_to_simplex_chat_founder"><![CDATA[Soru sormak ve güncellemeleri almak için <font color="#0088ff">SimpleX Chat geliştiricilerine bağlanabilirsiniz</font>.]]></string> <string name="you_can_hide_or_mute_user_profile">Bir kullanıcının profilini gizleyebilir veya sessize alabilirsiniz - menü için basılı tutun.</string> <string name="you_must_use_the_most_recent_version_of_database">Sohbet veritabanınızın en son sürümünü SADECE bir cihazda kullanmalısınız, aksi takdirde bazı kişilerden daha fazla mesaj alamayabilirsiniz.</string> <string name="wrong_passphrase">Yanlış veritabanı parolası</string> @@ -939,7 +933,7 @@ <string name="v4_6_reduced_battery_usage_descr">Daha fazla gelişme yakında geliyor!</string> <string name="only_stored_on_members_devices">(sadece grup üyeleri tarafından saklanır)</string> <string name="markdown_help">markdown yardımı</string> - <string name="no_info_on_delivery">Gönderi hakkında bilgi yok</string> + <string name="no_info_on_delivery">Gönderi bilgisi yok</string> <string name="no_selected_chat">Seçili sohbet yok</string> <string name="add_contact">Tek seferlik davet bağlantısı</string> <string name="receipts_groups_enable_for_all">Tüm gruplar için etkinleştir</string> @@ -976,7 +970,7 @@ <string name="to_connect_via_link_title">Link ile bağlanmak için</string> <string name="this_link_is_not_a_valid_connection_link">Bu geçerli bir bağlantı linki değil</string> <string name="this_QR_code_is_not_a_link">Bu QR kodu bir bağlantı değil!</string> - <string name="read_more_in_user_guide_with_link"><![CDATA[Daha fazla bilgi için <font color=#0088ff>Kullanıcı Kılavuzu</font>.]]></string> + <string name="read_more_in_user_guide_with_link"><![CDATA[Daha fazla bilgi için <font color="#0088ff">Kullanıcı Kılavuzu</font>.]]></string> <string name="paste_button">Yapıştır</string> <string name="this_string_is_not_a_connection_link">Bu dize bir bağlantı linki değil!</string> <string name="rate_the_app">Uygulamaya puan verin</string> @@ -1001,10 +995,10 @@ <string name="read_more_in_github">GitHub repomuzda daha fazlasını okuyun.</string> <string name="onboarding_notifications_mode_periodic">Periyodik</string> <string name="onboarding_notifications_mode_title">Gizli bildirimler</string> - <string name="paste_the_link_you_received">Alınan linki yapıştır</string> + <string name="paste_the_link_you_received">Aldığın bağlantıyı yapıştır</string> <string name="unknown_database_error_with_info">Bilinmeyen veri tabanı hatası: %s</string> <string name="open_chat">Sohbeti aç</string> - <string name="restore_database_alert_desc">Veritabanı yedeğini geri yükledikten sonra önceki şifreyi girin. Bu işlem geri alınamaz.</string> + <string name="restore_database_alert_desc">Veritabanı yedeğini geri yükledikten sonra önceki şifreyi girin. Bu eylem geri alınamaz.</string> <string name="network_option_ping_interval">PING aralığı</string> <string name="network_option_protocol_timeout_per_kb">KB başına protokol zaman aşımı</string> <string name="unhide_chat_profile">Sohbet profilini gizlemeyi kaldır</string> @@ -1020,7 +1014,7 @@ <string name="unfavorite_chat">Favorilerden çıkar</string> <string name="make_profile_private">Sohbeti gizli yap!</string> <string name="profile_update_will_be_sent_to_contacts">Profil güncellemesi kişilerinize gönderilecektir.</string> - <string name="read_more_in_github_with_link"><![CDATA[<font color=#0088ff>GitHub repomuzda</font> daha fazlasını okuyun.]]></string> + <string name="read_more_in_github_with_link"><![CDATA[<font color="#0088ff">GitHub repomuzda</font> daha fazlasını okuyun.]]></string> <string name="alert_text_fragment_please_report_to_developers">Lütfen geliştiricilere bildirin.</string> <string name="users_delete_with_connections">Profil ve sunucu bağlantıları</string> <string name="user_unhide">gizlemeyi kaldır</string> @@ -1063,10 +1057,501 @@ <string name="tap_to_activate_profile">Profili etkinleştirmek için dokun.</string> <string name="stop_chat_confirmation">Durdur</string> <string name="stop_sharing_address">Adres paylaşmayı durdur?</string> - <string name="send_receipts_disabled">kapalı</string> + <string name="send_receipts_disabled">devre dışı</string> <string name="turn_off_battery_optimization_button">İzin ver</string> <string name="error">Hata</string> <string name="stop_sharing">Paylaşmayı durdur</string> <string name="stop_rcv_file__title">Dosya almayı durdur?</string> <string name="stop_chat_question">Sohbeti durdur?</string> + <string name="expand_verb">Genişlet</string> + <string name="connect_plan_repeat_connection_request">Bağlantı isteğini tekrarla?</string> + <string name="no_details">detay yok</string> + <string name="database_initialization_error_desc">Veri tabanı düzgün çalışmıyor. Daha fazla bilgi için dokunun</string> + <string name="opensource_protocol_and_code_anybody_can_run_servers">Açık kaynaklı protokol ve kod - sunucuları herkes çalıştırabilir.</string> + <string name="rcv_group_event_open_chat">Aç</string> + <string name="settings_notification_preview_mode_title">Önizlemeyi göster</string> + <string name="v5_3_encrypt_local_files">Depolanan dosyaları ve medyayı şifrele</string> + <string name="only_you_can_send_voice">Sadece sen sesli mesaj gönderebilirsin.</string> + <string name="update_network_settings_confirmation">Güncelle</string> + <string name="database_backup_can_be_restored">Veritabanı parolasını değiştirme girişimi tamamlanmadı.</string> + <string name="update_database_passphrase">Veri tabanı parolasını güncelle</string> + <string name="turn_off_system_restriction_button">Uygulama ayarlarını aç</string> + <string name="enable_automatic_deletion_message">Bu eylem geri alınamaz - seçilenden daha önce gönderilen ve alınan mesajlar silinecektir. Birkaç dakika sürebilir.</string> + <string name="create_group_button">Grup oluştur</string> + <string name="custom_time_picker_select">Seç</string> + <string name="only_you_can_make_calls">Sadece sen arama yapabilirsin.</string> + <string name="new_mobile_device">Yeni mobil cihaz</string> + <string name="use_chat">Sohbeti kullan</string> + <string name="multicast_connect_automatically">Otomatik olarak bağlan</string> + <string name="share_verb">Paylaş</string> + <string name="rcv_group_event_n_members_connected">%s, %s ve %d diğer üye bağlandı</string> + <string name="only_your_contact_can_make_calls">Sadece senin kişin arama yapabilir.</string> + <string name="desktop_address">Masaüstü adresi</string> + <string name="smp_servers_test_some_failed">Bazı sunucular testi geçemedi:</string> + <string name="chat_with_the_founder">Sorularınızı ve fikirlerinizi gönderin</string> + <string name="delete_files_and_media_desc">Bu eylem geri alınamaz - tüm alınan ve gönderilen dosyalar ve medyalar silinecek. Düşük çözünürlükteki resimlar kalacaktır.</string> + <string name="encrypt_local_files">Yerel dosyaları şifrele</string> + <string name="ntf_channel_calls">SimpleX Chat aramaları</string> + <string name="v5_3_new_desktop_app">Yeni masaüstü uygulaması!</string> + <string name="v5_3_new_interface_languages">6 yeni arayüz dili</string> + <string name="notification_preview_mode_contact_desc">Sadece kişiyi göster</string> + <string name="connect_plan_group_already_exists">Grup zaten mevcut!</string> + <string name="icon_descr_speaker_on">Hoparlör açık</string> + <string name="only_your_contact_can_send_voice">Sadece senin kişin sesli mesaj gönderebilir.</string> + <string name="in_developing_desc">Bu özellik henüz desteklenmiyor. Bir sonraki sürümü deneyin.</string> + <string name="open_on_mobile_and_scan_qr_code"><![CDATA[Mobile uygulamadan <i>Masaüstünden kullan</i> seçeneğini aç ve karekodu okut.]]></string> + <string name="thank_you_for_installing_simplex">SimpleX Chat\'i yüklediğiniz için teşekkürler!</string> + <string name="skip_inviting_button">Üyeleri davet etmeyi atla</string> + <string name="connect_plan_already_connecting">Zaten bağlanılıyor!</string> + <string name="icon_descr_send_message">Mesaj Gönder</string> + <string name="contact_you_shared_link_with_wont_be_able_to_connect">Bu bağlantıyı paylaştığınız kişi bağlanamayacak!</string> + <string name="desktop_incompatible_version">Uyumsuz sürüm</string> + <string name="new_desktop"><![CDATA[<i>(yeni)</i>]]></string> + <string name="notification_preview_mode_message_desc">Kişiyi ve mesajı göster</string> + <string name="v5_4_better_groups">Daha iyi gruplar</string> + <string name="video_decoding_exception_desc">Videonun kodu çözülemiyor. Lütfen farklı bir video deneyin veya geliştiricilerle iletişime geçin.</string> + <string name="non_fatal_errors_occured_during_import">İçe aktarma sırasında bir takım hatlar oluştu - daha fazla detay için sohbet konsoluna bakabilirsiniz.</string> + <string name="show_developer_options">Geliştirici seçeneklerini göster</string> + <string name="rcv_group_event_1_member_connected">%s bağlandı</string> + <string name="network_disable_socks_info">Onaylarsanız, mesajlaşma sunucuları IP adresinizi ve sağlayıcınızı - hangi sunuculara bağlandığınızı - görebilecektir.</string> + <string name="share_with_contacts">Kişilerle paylaş</string> + <string name="chat_item_ttl_seconds">%s saniye (sn)</string> + <string name="recipient_colon_delivery_status">%s: %s</string> + <string name="system_restricted_background_desc">SimpleX arka planda çalışamaz. Bildirimleri sadece uygulama çalışırken alırsınız.</string> + <string name="connect_plan_connect_via_link">Bağlantı ile bağlanılsın mı?</string> + <string name="database_encryption_will_be_updated_in_settings">Veri tabanı şifreleme parolası güncellenecek ve ayarlarda depolanacaktır.</string> + <string name="connect_plan_already_joining_the_group">Zaten gruba bağlanılıyor!</string> + <string name="group_members_n">%s, %s ve %d üye</string> + <string name="this_device">Bu cihaz</string> + <string name="share_address_with_contacts_question">Adresi kişilerle paylaş?</string> + <string name="system_restricted_background_in_call_desc">Uygulama arka planda 1 dakika kaldıktan sonra kapatılabilir.</string> + <string name="text_field_set_contact_placeholder">Kişi ismini ayarla…</string> + <string name="send_us_an_email">Bize e-posta gönder</string> + <string name="v4_2_security_assessment_desc">SimpleX Chat\'in güvenliği Trail of Bits tarafından denetlenmiştir.</string> + <string name="simplex_service_notification_title">SimpleX Chat hizmeti</string> + <string name="is_verified">%s onaylı</string> + <string name="password_to_show">Göserilecek parola</string> + <string name="incognito_info_allows">Tek bir sohbet profilinde, aralarında herhangi bir veri paylaşımı olmadan birden fazla anonim bağlantı kurmaya izin verir.</string> + <string name="select_contacts">Kişileri seç</string> + <string name="v4_6_chinese_spanish_interface_descr">Kullanıcılara teşekkürler - Weblate aracılığıyla katkıda bulunun!</string> + <string name="v5_3_simpler_incognito_mode">Basitleştirilmiş gizli mod</string> + <string name="update_network_settings_question">Ağ ayarları güncellensin mi?</string> + <string name="shutdown_alert_question">Kapat?</string> + <string name="you_invited_a_contact">Bir kişiyi davet ettin</string> + <string name="is_not_verified">%s onaylı değil</string> + <string name="this_device_name">Bu cihazın ismi</string> + <string name="smp_server_test_upload_file">Dosya yükle</string> + <string name="network_use_onion_hosts_required">Gerekli</string> + <string name="ntf_channel_messages">SimpleX Chat mesajlar</string> + <string name="share_link">Bağlantı paylaş</string> + <string name="icon_descr_simplex_team">SimpleX Ekibi</string> + <string name="rcv_group_event_3_members_connected">%s, %s ve %s bağlandı</string> + <string name="network_options_revert">Geri al</string> + <string name="settings_section_title_socks">SOCKS VEKİLİ</string> + <string name="desktop_devices">Masaüstür cihazlar</string> + <string name="smp_servers">SMP sunucuları</string> + <string name="not_compatible">Uyumlu değil!</string> + <string name="v4_4_verify_connection_security">Bağlantı güvenliğini onayla</string> + <string name="connect_with_contact_name_question">%1$s ile bağlan?</string> + <string name="remove_member_button">Üyeyi çıkar</string> + <string name="open_database_folder">Veri tabanı dosyasını aç</string> + <string name="settings_section_title_use_from_desktop">Masaüstünden kullan</string> + <string name="network_proxy_port">port %d</string> + <string name="share_address">Adres paylaş</string> + <string name="connect_plan_repeat_join_request">Bağlantı talebini tekrarla?</string> + <string name="button_remove_member_question">Üyeyi çıkar?</string> + <string name="verify_security_code">Güvenlik kodunu onayla</string> + <string name="show_dev_options">Göster:</string> + <string name="receipts_section_groups">Küçük gruplar (maks 20)</string> + <string name="v5_3_new_interface_languages_descr">Arapça, Bulgarca, Fince, İbranice, Tayca ve Ukraynaca - kullanıcılar ve Weblate sayesinde.</string> + <string name="port_verb">Port</string> + <string name="connection_you_accepted_will_be_cancelled">Kabul ettiğiniz bağlantı iptal edilecek!</string> + <string name="connect_plan_open_group">Grubu aç</string> + <string name="privacy_show_last_messages">Son mesajları göster</string> + <string name="this_device_version"><![CDATA[<i>bu cihaz s%s</i>]]></string> + <string name="core_simplexmq_version">simplexmq: v%s (%2s)</string> + <string name="update_database">Güncelle</string> + <string name="this_device_name_shared_with_mobile">Cihaz ismi bağlı olduğu mobil istemci ile paylaşılacak.</string> + <string name="v5_3_new_desktop_app_descr">Masaüstü uygulamasında yeni bir profil oluştur. 💻</string> + <string name="set_contact_name">Kişi ismini ayarla</string> + <string name="verify_code_on_mobile">Kodu mobilde onayla</string> + <string name="share_image">Medya paylaş…</string> + <string name="passphrase_will_be_saved_in_settings">Parola, siz onu değiştirdikten veya uygulamayı yeniden başlattıktan sonra ayarlarda düz metin olarak depolanacak.</string> + <string name="paste_the_link_you_received_to_connect_with_your_contact">Kişinizle bağlantı kurmak için aldığınız bağlantıyı yapıştırın…</string> + <string name="settings_shutdown">Kapat</string> + <string name="icon_descr_sent_msg_status_sent">gönderildi</string> + <string name="send_live_message">Canlı mesaj gönder</string> + <string name="enter_this_device_name">Bu cihazın adını girin…</string> + <string name="smp_servers_per_user">Mevcut sohbet profilinizin yeni bağlantıları için sunucular</string> + <string name="show_QR_code">QR kodu göster</string> + <string name="network_socks_proxy_settings">SOCKS proxy ayarları</string> + <string name="rcv_group_events_count">%d grup etkinlikleri</string> + <string name="invalid_name">Geçersiz isim!</string> + <string name="la_lock_mode">SimpleX Kilit modu</string> + <string name="share_file">Dosya paylaş…</string> + <string name="periodic_notifications_desc">Uygulama yeni mesajları periyodik olarak alır - günde pilin yüzde birkaçını kullanır. Uygulama anlık bildirimleri kullanmaz - cihazınızdan gelen veriler sunuculara gönderilmez.</string> + <string name="first_platform_without_user_ids">Herhangi bir kullanıcı tanımlayıcısı olmayan ilk platform - tasarım gereği gizli.</string> + <string name="icon_descr_speaker_off">Hoparlör kapalı</string> + <string name="sync_connection_force_desc">Şifreleme çalışıyor ve yeni bir şifreleme anlaşması gerekli değil. Yoksa bağlantı hataları ortaya çıkabilir!</string> + <string name="show_call_on_lock_screen">Göster</string> + <string name="send_verb">Gönder</string> + <string name="paste_desktop_address">Masaüstü adresini yapıştır</string> + <string name="verify_code_with_desktop">Kodu masaüstü ile onayla</string> + <string name="scan_qr_code_from_desktop">Masaüstünden karekodu tara</string> + <string name="image_descr_simplex_logo">SimpleX logo</string> + <string name="devices">Cihazlar</string> + <string name="delete_chat_profile_action_cannot_be_undone_warning">Bu eylem geri alınamaz - profiliniz, kişileriniz, mesajlarınız ve dosyalarınız geri döndürülemez şekilde kaybolacaktır.</string> + <string name="v5_4_more_things_descr">- isteğe bağlı olarak silinen kişileri bildirme. +\n- boşluklu profil adları. +\n- ve daha fazlası!</string> + <string name="la_notice_title_simplex_lock">SimpleX Kilit</string> + <string name="connect_via_member_address_alert_desc">Bu grup üyesine bağlantı isteği gönderilecek.</string> + <string name="only_your_contact_can_add_message_reactions">Sadece senin kişin mesaj tepkileri ekleyebilir.</string> + <string name="settings_is_storing_in_clear_text">Parola, ayarlarda düz metin olarak saklanır.</string> + <string name="auth_simplex_lock_turned_on">SimpleX Kilit aktif</string> + <string name="terminal_always_visible">Yeni pencerede konsolu göster</string> + <string name="scan_from_mobile">Mobilden tara</string> + <string name="verify_connections">Bağlantıları onayla</string> + <string name="share_message">Mesaj paylaş…</string> + <string name="alert_text_msg_bad_hash">Önceki mesajın hash\'i farklı.</string> + <string name="lock_not_enabled">SimpleX Kilit aktif değil!</string> + <string name="chat_lock">SimpleX Kilit</string> + <string name="connect_via_member_address_alert_title">Direkt bağlanılsın mı?</string> + <string name="receipts_section_description">Bu ayarlar mevcut profiliniz içindir</string> + <string name="smp_servers_test_failed">Sunucu testi başarısız!</string> + <string name="verify_connection">Bağlantıyı onayla</string> + <string name="add_contact_or_create_group">Yeni sohbet başlat</string> + <string name="connect__your_profile_will_be_shared">Profiliniz %1$s paylaşılacaktır.</string> + <string name="v5_4_incognito_groups_descr">Rastgele bir profil kullanarak grup oluştur.</string> + <string name="connect_plan_you_are_already_joining_the_group_via_this_link">Gruba zaten bu bağlantı üzerinden katılıyorsunuz.</string> + <string name="your_chat_profile_will_be_sent_to_your_contact">Sohbet profiliniz kişinize +\ngönderilecek</string> + <string name="invite_prohibited_description">Gizli bir profil paylaştığınız kişiyi ana profilinizi kullandığınız gruba davet etmeye çalışıyorsunuz</string> + <string name="rcv_conn_event_verification_code_reset">güvenlik kodu değiştirildi</string> + <string name="v4_6_audio_video_calls_descr">Bluetooth desteği ve diğer iyileştirmeler.</string> + <string name="icon_descr_settings">Ayarlar</string> + <string name="settings_section_title_settings">AYARLAR</string> + <string name="compose_send_direct_message_to_connect">Bağlanmak için direkt mesaj gönderin</string> + <string name="security_code">Güvenlik kodu</string> + <string name="v5_4_better_groups_descr">Daha hızlı gruplara katılma ve daha güvenilir mesajlar.</string> + <string name="group_main_profile_sent">Sohbet profiliniz grup üyelerine gönderilecek</string> + <string name="connect_plan_connect_to_yourself">Kendine bağlan?</string> + <string name="notifications_mode_periodic">Periyodik olarak başlar</string> + <string name="connect_plan_this_is_your_own_simplex_address">Bu sizin kendi SimpleX adresiniz!</string> + <string name="v4_3_irreversible_message_deletion_desc">Kişileriniz tam mesaj silme işlemine izin verebilir.</string> + <string name="icon_descr_sent_msg_status_send_failed">gönderme başarısız</string> + <string name="sender_may_have_deleted_the_connection_request">Gönderen kişi bağlantı isteğini silmiş olabilir.</string> + <string name="create_chat_profile">Sohbet profili oluştur</string> + <string name="error_sending_message_contact_invitation">Davetiye gönderirken hata</string> + <string name="you_can_start_chat_via_setting_or_by_restarting_the_app">Sohbeti uygulama Ayarları/Veritabanı üzerinden veya uygulamayı yeniden başlatarak başlatabilirsiniz.</string> + <string name="connect_to_desktop">Masaüstüne bağlan</string> + <string name="button_send_direct_message">Doğrudan mesaj gönder</string> + <string name="connect_plan_you_have_already_requested_connection_via_this_address">Bu adres üzerinden zaten bağlantı talebinde bulundunuz!</string> + <string name="member_contact_send_direct_message">doğrudan mesaj gönder</string> + <string name="sender_cancelled_file_transfer">Gönderen kişi dosya aktarımını iptal etti.</string> + <string name="only_you_can_delete_messages">Mesajları yalnızca siz geri döndürülemez şekilde silebilirsiniz (kişiniz bunları silinmek üzere işaretleyebilir). (24 saat içinde)</string> + <string name="connect_plan_you_are_already_connecting_to_vName"><![CDATA[Zaten <b>%1$s</b>’ye bağlanıyorsunuz.]]></string> + <string name="whats_new_thanks_to_users_contribute_weblate">Kullanıcılara teşekkürler - Weblate aracılığıyla katkıda bulunun!</string> + <string name="lock_mode">Kilit modu</string> + <string name="only_one_device_can_work_at_the_same_time">Aynı anda yalnızca bir cihaz çalışabilir</string> + <string name="connect_plan_you_are_already_joining_the_group_vName"><![CDATA[Zaten <b>%1$s</b> grubuna katılıyorsunuz.]]></string> + <string name="group_invitation_tap_to_join">Katılmak için dokun</string> + <string name="v5_0_polish_interface_descr">Kullanıcılara teşekkürler - Weblate aracılığıyla katkıda bulunun!</string> + <string name="v5_4_link_mobile_desktop_descr">Güvenli kuantum dirençli protokol ile.</string> + <string name="star_on_github">Bize GitHub\'da yıldız verin</string> + <string name="auth_you_will_be_required_to_authenticate_when_you_start_or_resume">Arka planda 30 saniye kaldıktan sonra uygulamayı başlattığınızda veya devam ettirdiğinizde kimlik doğrulaması yapmanız gerekecektir.</string> + <string name="v4_5_italian_interface_descr">Kullanıcılara teşekkürler - Weblate aracılığıyla katkıda bulunun!</string> + <string name="waiting_for_desktop">Masaüstü bekleniyor…</string> + <string name="database_is_not_encrypted">Sohbet veritabanınız şifreli değildir - korumak için parola ayarlayın.</string> + <string name="you_will_still_receive_calls_and_ntfs">Aktif olduklarında sessize alınmış profillerden arama ve bildirim almaya devam edersiniz.</string> + <string name="connect_plan_you_are_already_in_group_vName"><![CDATA[Zaten<b> %1$s </b>grubundasınız.]]></string> + <string name="v4_4_french_interface_descr">Kullanıcılara teşekkürler - Weblate aracılığıyla katkıda bulunun!</string> + <string name="connect_plan_you_are_already_connecting_via_this_one_time_link">Bu tek seferlik bağlantı üzerinden zaten bağlanıyorsunuz!</string> + <string name="non_content_uri_alert_text">Geçersiz bir dosya yolu paylaştınız. Sorunu uygulama geliştiricilerine bildirin.</string> + <string name="disable_notifications_button">Bildirimleri devre dışı bırak</string> + <string name="non_content_uri_alert_title">Geçersiz dosya yolu</string> + <string name="only_your_contact_can_delete">Yalnızca kişiniz mesajları geri alınamaz şekilde silebilir (silinmeleri için işaretleyebilirsiniz). (24 saat içinde)</string> + <string name="database_will_be_encrypted_and_passphrase_stored_in_settings">Veritabanı şifrelenecek ve parola ayarlarda depolanacak.</string> + <string name="v5_4_block_group_members">Grup üyelerini engelle</string> + <string name="feature_received_prohibited">alınmış, yasaklanmış</string> + <string name="error_xftp_test_server_auth">Sunucunun yükleme yapması için yetkilendirilmesi gerekli, şifreyi kontrol et</string> + <string name="encryption_renegotiation_error">Şifreleme yeniden aşma hatası</string> + <string name="smp_servers_preset_server">Ön ayarlı sunucu</string> + <string name="feature_cancelled_item">%s iptal edildi</string> + <string name="rcv_direct_event_contact_deleted">silinmiş kişi</string> + <string name="network_option_tcp_connection_timeout">TCP bağlantısı zaman aşımına uğradı</string> + <string name="mtr_error_different">uygulama/veritabanı içinde farklı değişim: %s / %s</string> + <string name="using_simplex_chat_servers">SimpleX Chat serverları kullanılıyor.</string> + <string name="smp_servers_preset_add">Ön ayarlı sunucular ekle</string> + <string name="secret_text">gizli</string> + <string name="receipts_groups_disable_for_all">Bütün gruplar için devre dışı bırak</string> + <string name="v4_6_group_welcome_message_descr">Yeni üyeler için gösterilecek mesajı seç!</string> + <string name="stop_snd_file__message">Dosya gönderimi durdurulacaktır.</string> + <string name="moderated_description">yönetildi</string> + <string name="error_creating_member_contact">Üye bağlantısı oluşturulurken hata</string> + <string name="sending_delivery_receipts_will_be_enabled">Çoklu gönderim bütün kişiler için etkinleştirilecektir.</string> + <string name="ensure_xftp_server_address_are_correct_format_and_unique">XFTP sunucu adreslerinin doğru formatta olduğundan, satırın ayrılmış ve kopyalanmamış olduğundan emin olun.</string> + <string name="refresh_qr_code">Yenile</string> + <string name="socks_proxy_setting_limitations"><![CDATA[<b>Lütfen unutmayın</b>: mesaj ve dosya yönlendiricileri SOCKS vekili tarafından bağlandı. Aramalar ve bağlantı ön gösterimleri doğrudan bağlantı kullanıyor.]]></string> + <string name="mobile_tap_open_in_mobile_app_then_tap_connect_in_app"><![CDATA[📱mobil: <b>Telefon uygulamasında aç</b> seçeneğine tıkla, sonra uygulama içinden <b>Bağlan</b> seçeneğine tıkla.]]></string> + <string name="smp_server_test_secure_queue">Gizli sıra</string> + <string name="connected_desktop">Masaüstü bağlandı</string> + <string name="group_members_2">%s ve %s</string> + <string name="v5_2_fix_encryption">Bağlantılarını koru</string> + <string name="received_message">Alınmış mesaj</string> + <string name="you_can_make_address_visible_via_settings">Ayarlardan SimpleX kişilerinize görünür yapabilirsiniz.</string> + <string name="connect_plan_join_your_group">Grubuna bağlanılsın mı?</string> + <string name="v5_4_link_mobile_desktop">Telefon veya bilgisayar uygulamalarını bağla! 🔗</string> + <string name="connect__a_new_random_profile_will_be_shared">Yeni bir rasgele profil paylaşılacaktır.</string> + <string name="receipts_contacts_override_enabled">Alıcılar %d bağlantıları için etkinleştirilecektir</string> + <string name="moderate_message_will_be_marked_warning">Mesaj herkes için yönetilmiş olarak işaretlenecek.</string> + <string name="connect_plan_this_is_your_own_one_time_link">Bu senin kendi tek-kullanımlık bağlantın!</string> + <string name="marked_deleted_items_description">%d mesajları silinmiş olarak işaretlendi</string> + <string name="connect_use_new_incognito_profile">Yeni sahte profil kullan</string> + <string name="chat_is_stopped_you_should_transfer_database">Sohbet durduruldu. Eğer çoktan başka bir cihazda bu veritabanını kullandıysan,sohbeti başlatmadan önce veritabanını geri aktarmalısın.</string> + <string name="send_link_previews">Bağlantı ön izlemelerini gönder</string> + <string name="sending_via">Aracılığıyla gönderiliyor</string> + <string name="icon_descr_sent_msg_status_unauthorized_send">yetkisiz gönder</string> + <string name="v4_5_transport_isolation">Ulaşım izolasyonu</string> + <string name="sending_delivery_receipts_will_be_enabled_all_profiles">Çoklu gönderim bütün görünebilir sohbet profillerinde etkinleştirilecektir.</string> + <string name="system_restricted_background_in_call_warn"><![CDATA[Arkaplanda arama yapmak için, lütfen uygulama ayarlarından <b>Uygulama pil kullanımı</b> / <b>Sınırsız</b> seçeneğini seç.]]></string> + <string name="callstate_received_confirmation">onaylama alındı…</string> + <string name="share_text_updated_at">Kayıt %s te güncellendi</string> + <string name="v5_3_encrypt_local_files_descr">Uygulama yeni yerel dosyaları şifreler (videolar dışında).</string> + <string name="sender_at_ts">%s , %s de</string> + <string name="network_use_onion_hosts_required_desc_in_alert">Bağlantı için Onion ana bilgisayarları gerekli olacaktır.</string> + <string name="receipts_contacts_title_disable">Alıcılar devre dışı bırakılsın mı?</string> + <string name="sync_connection_force_question">Bağlantı yeniden senkronizasyonunu şifrele?</string> + <string name="receipts_section_description_1">Grup ayarlarından ve kişilerden geçersiz kılınmış olabilirler</string> + <string name="recent_history_is_not_sent_to_new_members">Yeni üyelere geçmiş gönderilmedi.</string> + <string name="v4_2_security_assessment">Güvenlik değerlendirmesi</string> + <string name="retry_verb">Yeniden dene</string> + <string name="network_use_onion_hosts_prefer_desc_in_alert">Onion ana bilgisayarları mümkün olduğunda kullanılacaktır.</string> + <string name="network_enable_socks_info">Sunuculara %d bağlantı noktasındaki vekil SOCKS aracılığıyla erişilsin mi? Vekil bu seçeneği etkinleştirmeden önce başlatılmak zorundadır.</string> + <string name="v5_4_block_group_members_descr">İstenmeyen mesajları gizlemek için.</string> + <string name="error_smp_test_failed_at_step">Test %s adımında hata yaşandı.</string> + <string name="disable_onion_hosts_when_not_supported"><![CDATA[<i> .onion ana bilgisayarlarını kullan</i> seçeneğini eğer SOCKS vekili destek vermiyorsa devre dışı bırak]]></string> + <string name="you_can_change_it_later">Rasgele şifreler düz metin olarak ayarlarda saklanacaktır. +\nBunu sonra değiştirebilirsin.</string> + <string name="ensure_smp_server_address_are_correct_format_and_unique">SMP sunucu adreslerinin doğru formatta olduğundan, satırın ayrılmış ve kopyalanmamış olduğundan emin olun.</string> + <string name="group_invitation_tap_to_join_incognito">Sahte İsimle katılmak için tıkla</string> + <string name="network_use_onion_hosts_no_desc">Onion ana bilgisayarları kullanılmayacaktır.</string> + <string name="set_password_to_export">Dışarıya çıkarmak için parola belirle</string> + <string name="snd_conn_event_ratchet_sync_started">%s için şifreleme kabul ediliyor…</string> + <string name="receipts_groups_override_disabled">Alıcılar %d grupları için devre dışı bırakılacak</string> + <string name="notification_new_contact_request">Yeni bağlantı isteği</string> + <string name="unlink_desktop_question">Bilgisayarla bağlantıyı kes?</string> + <string name="camera_not_available">Kamera hazır değil</string> + <string name="use_simplex_chat_servers__question">SimpleX Chat sunucularını kullan?</string> + <string name="linked_desktop_options">Bağlanmış bilgisayar ayarları</string> + <string name="developer_options">Veritabanı kimlikleri ve Taşıma izolasyonu seçeneği.</string> + <string name="network_option_ping_count">PING sayısı</string> + <string name="update_network_session_mode_question">Ulaşım izolasyonu modu güncellensin mi?</string> + <string name="random_port">Rasgele</string> + <string name="linked_desktops">Bağlanmış bilgisayarlar</string> + <string name="discover_on_network">Yerel ağ aracılığıyla keşfet</string> + <string name="muted_when_inactive">Aktif değilken susturuldu!</string> + <string name="rcv_group_and_other_events">ve %d diğer etkinlikler</string> + <string name="network_session_mode_transport_isolation">Ulaşım izolazyonu</string> + <string name="v5_3_discover_join_groups">Keşfet ve gruplara katıl</string> + <string name="v5_4_incognito_groups">Gizli gruplar</string> + <string name="user_unmute">Susturmayı kaldır</string> + <string name="share_text_sent_at">%s de gönderildi</string> + <string name="enable_sending_recent_history">Yeni katılımcılara 100e kadar son mesajlar gönder</string> + <string name="moderate_verb">Yönet</string> + <string name="moderated_items_description">%1$d mesajları %2$s tarafından yönetildi</string> + <string name="remove_passphrase_from_settings">Ayarlardaki parola silinsin mi?</string> + <string name="receipts_contacts_title_enable">Alıcılar etkinleştirilsin mi?</string> + <string name="tap_to_start_new_chat">Yeni bir sohbet başlatmak için tıkla</string> + <string name="network_use_onion_hosts_no_desc_in_alert">Onion ana bilgisayarları kullanılmayacaktır.</string> + <string name="unblock_member_button">Kişinin engelini kaldır</string> + <string name="relay_server_if_necessary">Yönlendirici sunucusu sadece lazım ise kullanılacak. Diğer taraf IP adresini görebilir.</string> + <string name="remote_host_was_disconnected_toast"><![CDATA[Telefon bağlantılı <b>%s</b> ın bağlantısı kesildi]]></string> + <string name="smp_servers_test_server">Sunucuyu test et</string> + <string name="conn_stats_section_title_servers">SUNUCULAR</string> + <string name="smp_servers_test_servers">Sunucuları test et</string> + <string name="privacy_message_draft">Mesaj taslağı</string> + <string name="v5_2_disappear_one_message">Bir mesajı yok edin</string> + <string name="add_contact_button_to_create_link_or_connect_via_link"><![CDATA[<b>Kişi ekle</b> yeni bir davet bağlantısı oluşturmak için, veya aldığın bir davet bağlantısından bağlan.]]></string> + <string name="disable_sending_recent_history">Yeni üyelere geçmişi gönderme.</string> + <string name="icon_descr_contact_checked">Kişi doğrulandı</string> + <string name="use_random_passphrase">Rasgele parola kullan</string> + <string name="v5_0_app_passcode_descr">Sistem yetkilendirilmesi yerine ayarla.</string> + <string name="run_chat_section">SOHBETİ ÇALIŞTIR</string> + <string name="network_disable_socks">Direkt internet bağlantısı kullan?</string> + <string name="rcv_group_event_updated_group_profile">grup profili güncellendi</string> + <string name="network_use_onion_hosts_required_desc">Onion ana bilgisayarları bağlantı için gerekli olacaktır. +\nLütfen unutmayın: artık .onion adresi olmayan sunuculara bağlanamayacaksınız.</string> + <string name="switch_receiving_address_desc">Alınan adres başka bir sunucuda değiştirilecektir. Adres değişimi gönderen çevrimiçi olunca tamamlanacaktır.</string> + <string name="error_smp_test_server_auth">Sunucunun sıralar oluşturması için yetkilendirilmesi gerekli, şifreyi kontrol et</string> + <string name="system_restricted_background_in_call_title">Arkaplan araması yok</string> + <string name="group_is_decentralized">Tamamiyle merkezi olmayan - sadece üyelere görünür.</string> + <string name="error_showing_content">içerik gösterilirken hata</string> + <string name="or_show_this_qr_code">Veya bu kodu göster</string> + <string name="above_then_preposition_continuation">üzerinde, ardından:</string> + <string name="linked_mobiles">Bağlanmış telefonlar</string> + <string name="recent_history_is_sent_to_new_members">Yeni üyelere 100e kadar en son mesajlar gönderildi.</string> + <string name="sent_message">Gönderilmiş mesaj</string> + <string name="save_passphrase_in_settings">Ayarlarda parolayı kaydet</string> + <string name="upgrade_and_open_chat">Yükselt ve sohbeti aç</string> + <string name="code_you_scanned_is_not_simplex_link_qr_code">Tarattığın kod SimpleX QR kodu bağlantısı değil.</string> + <string name="send_receipts_disabled_alert_msg">Bu grupta %1$d den fazla kişi var,çoklu gönderim yapılamıyor.</string> + <string name="connected_to_desktop">Masaüstüne bağlandı</string> + <string name="error_smp_test_certificate">Muhtemelen, sunucu adresindeki sertifika parmak izi doğru değil</string> + <string name="v5_2_message_delivery_receipts_descr">✅ özlediğimiz ikinci tik!</string> + <string name="clear_verification">Doğrulamayı temizle</string> + <string name="setup_database_passphrase">Veritabanı parolası ayarla</string> + <string name="the_text_you_pasted_is_not_a_link">Yapıştırdığın bağlantı bir SimpleX bağlantısı değil.</string> + <string name="color_sent_message">Gönderilmiş mesaj</string> + <string name="receipts_groups_title_disable">Gruplar için alıcılar devre dışı bırakılsın mı?</string> + <string name="relay_server_protects_ip">Aktarıcı sunucu IP adresinizi korur, ancak aramanın süresini gözlemleyebilir.</string> + <string name="loading_remote_file_title">Dosya yükleniyor</string> + <string name="connecting_to_desktop">Masaüstüne bağlanıyor</string> + <string name="no_contacts_to_add">Eklenecek kişi yok</string> + <string name="v4_5_message_draft_descr">Son mesaj taslağını saklayın, ekleriyle birlikte.</string> + <string name="found_desktop">Bilgisayar bulundu</string> + <string name="alert_text_encryption_renegotiation_failed">Şifreleme yeniden aşması başarısız oldu.</string> + <string name="smp_servers_add_to_another_device">Başka bir cihaza ekle</string> + <string name="feature_offered_item_with_param">%s: %2s teklif etti</string> + <string name="error_showing_message">mesaj gösterilirken hata</string> + <string name="accept_contact_incognito_button">Takma Ad ile kabul et</string> + <string name="receipts_groups_override_enabled">Alıcılar %d grupları için etkinleştirilecektir</string> + <string name="correct_name_to">İsmi %s olarak düzelt?</string> + <string name="sync_connection_force_confirm">Bağlantıyı yeniden senkronize etmek</string> + <string name="waiting_for_mobile_to_connect">Bağlanmak için telefon bekleniyor:</string> + <string name="enable_camera_access">Kamera erişimini etkinleştir</string> + <string name="delete_messages__question">%d mesajlarını sil?</string> + <string name="marked_deleted_description">silinmiş olarak işaretlenmiş</string> + <string name="you_can_view_invitation_link_again">Bağlantı detaylarından davet bağlantısını yeniden görüntüleyebilirsin.</string> + <string name="link_a_mobile">Bir telefon bağla</string> + <string name="keep_unused_invitation_question">Kullanılmamış daveti tut?</string> + <string name="start_chat_question">Sohbet başlatılsın mı?</string> + <string name="set_database_passphrase">Veritabanı parolası ayarla</string> + <string name="share_this_1_time_link">Bu tek-kullanımlık davet bağlantısını paylaş</string> + <string name="unblock_member_question">Kişinin engeli kaldırılsın mı?</string> + <string name="blocked_items_description">%d mesajları engellendi</string> + <string name="create_group_button_to_create_new_group"><![CDATA[<b>Grup oluştur</b>: yeni bir grup oluşturmak için.]]></string> + <string name="icon_descr_video_asked_to_receive">Videoyu almak için soruldu</string> + <string name="open_port_in_firewall_desc">Telefon uygulamanın bilgisayarına bağlanmasına izin vermek için, güvenlik duvarın etkin ise bu portu aç</string> + <string name="block_member_button">Üye engelle</string> + <string name="receipts_contacts_override_disabled">Alıcılar %d bağlantıları için devre dışı bırakılacak</string> + <string name="receipts_groups_enable_keep_overrides">Etkinleştir (grup geçersiz kılmalarını tut)</string> + <string name="system_restricted_background_warn"><![CDATA[Bildirimleri etkinleştirmek için, Lütfen uygulama ayarlarından <b>Uygulama pil kullanımı</b> / <b>Sınırsız</b> seçeneğini seç.]]></string> + <string name="send_receipts_disabled_alert_title">Alıcılar devre dışı bırakıldı.</string> + <string name="set_group_preferences">Grup tercihlerini ayarla</string> + <string name="invalid_migration_confirmation">Geçerli olmayan taşıma onayı</string> + <string name="recent_history">Görünür geçmiş</string> + <string name="connected_mobile">Telefondan bağlandı</string> + <string name="group_member_status_complete">tamamlandı</string> + <string name="session_code">Oturum kodu</string> + <string name="smp_server_test_create_queue">Sıra başlat</string> + <string name="app_was_crashed">Görünüm çöktü</string> + <string name="callstate_received_answer">alınan cevap…</string> + <string name="delete_and_notify_contact">Sil ve kişiye haber ver</string> + <string name="simplex_service_notification_text">Mesajlar alınıyor…</string> + <string name="la_app_passcode">Uygulama şifresi</string> + <string name="rcv_group_event_2_members_connected">%s ve %s bağlandı</string> + <string name="delete_after">Sonra sil</string> + <string name="info_row_sent_at">Gönderildi</string> + <string name="smp_servers_preset_address">Önceden ayarlanmış sunucu adresi</string> + <string name="desktop_connection_terminated">Bağlantı sonlandırıldı</string> + <string name="updating_settings_will_reconnect_client_to_all_servers">Ayarları güncellemek alıcıyı bütün sunuculara yeniden bağlandıracak.</string> + <string name="unlink_desktop">Bağlantıyı kes</string> + <string name="feature_offered_item">%s teklif edildi</string> + <string name="icon_descr_received_msg_status_unread">okunmamış</string> + <string name="new_chat">Yeni sohbet</string> + <string name="send_live_message_desc">Bir canlı mesaj gönder - bu yazdıklarını anlık olarak alıcıya(lara) güncelleyen bir mesajdır</string> + <string name="remove_passphrase_from_keychain">Şifre Yöneticisindeki parola silinsin mi?</string> + <string name="settings_section_title_delivery_receipts">LERE GÖNDER</string> + <string name="connect_via_link_incognito">Takma adla bağlan</string> + <string name="always_use_relay">Her zaman yönlendirici kullan.</string> + <string name="auth_unlock">Kilidini aç</string> + <string name="unblock_member_desc">%s ten gelen mesajlar gösterilecek!</string> + <string name="error_enabling_delivery_receipts">Teslim alan alıcılar etkinleştirilirken hata!</string> + <string name="chat_preferences_contact_allows">Kişi izin verir</string> + <string name="alert_title_skipped_messages">Atlanmış mesajlar</string> + <string name="alert_text_msg_bad_id">Bir sonraki mesajın kimliği yanlış (bir öncekinden az veya aynı). +\nBazı hatalar nedeniyle veya bağlantı tehlikeye girdiğinde meydana gelebilir.</string> + <string name="notification_preview_somebody">Kişi gizlendi:</string> + <string name="many_people_asked_how_can_it_deliver"><![CDATA[Bir sürü kişi sordu: <i> eğer SimpleX’in hiç kullanıcı tanımlayıcısı yok, nasıl mesajları gönderiyor? </i>]]></string> + <string name="alert_text_skipped_messages_it_can_happen_when">Şu durumlarda gerçekleşebilir: +\n1. Mesajların süresi, gönderen istemcide 2 gün sonra veya sunucuda 30 gün sonra sona erdi. +\n2. Siz veya kişiniz eski veritabanı yedeğini kullandığınız için mesajın şifresini çözme işlemi başarısız oldu. +\n3. Bağlantı tehlikeye girdi.</string> + <string name="network_use_onion_hosts_prefer_desc">Onion ana bilgisayarları mümkün olduğu zaman kullanılacaktır.</string> + <string name="switch_verb">Değiştir</string> + <string name="open_port_in_firewall_title">Güvenlik duvarında port aç</string> + <string name="callstate_starting">başlatılıyor…</string> + <string name="network_socks_toggle_use_socks_proxy">SOCKS vekili kullan</string> + <string name="mtr_error_no_down_migration">veritabanı versiyonu uygulamadan daha yeni, ama %s için aşağı geçiş yok</string> + <string name="keychain_allows_to_receive_ntfs">Android Şifre Yöneticisi uygulamayı yeniden başlattıktan veya parolanı değiştirdikten sonra güvenle parolalarını tutmak için kullanılacaktır - bu bildirimleri almanı sağlayacaktır.</string> + <string name="send_receipts">Alıcılara gönder</string> + <string name="loading_chats">Sohbetler yükleniyor…</string> + <string name="chat_help_tap_button">Butona bas</string> + <string name="connection_error_auth_desc">Kişinin bağlantısını silmesi veya bağlantının çoktan kullanılması gibi bir durum yoksa, bu bir hata olabilir - lütfen bize bildirin. +\nBağlanmak için, lütfen kişiye başka bir bağlanma bağlantısı göndermesini isteyin ve stabil bir internet bağlantınız olduğunu kontrol edin.</string> + <string name="image_decoding_exception_desc">Bu fotoğraf deşifre edilemedi. Lütfen,başka bir fotoğraf deneyin veya geliştiricilerle iletişime geçin.</string> + <string name="disconnect_remote_hosts">Telefonların bağlantısını kes</string> + <string name="receiving_via">Aracılığıyla alınıyor</string> + <string name="share_text_moderated_at">%s de yönetildi</string> + <string name="disconnect_remote_host">Bağlantıyı kes</string> + <string name="renegotiate_encryption">Bağlantı yeniden senkronizasyonu şifrelemesi</string> + <string name="receipts_groups_disable_keep_overrides">Devre dışı bırak (grup geçersiz kılmalarını tut)</string> + <string name="smp_server_test_delete_queue">Silme sırası</string> + <string name="creating_link">Bağlantı oluşturuluyor…</string> + <string name="block_member_question">Üye engellensin mi?</string> + <string name="receipts_groups_title_enable">Gruplar için alıcılar etkinleştirilsin mi?</string> + <string name="group_member_role_author">yetkili</string> + <string name="v4_5_multiple_chat_profiles_descr">Farklı isimler, profil fotoğrafları ve ulaşım izolasyonu.</string> + <string name="network_use_onion_hosts">.onion ana bilgisayarlarını kullan</string> + <string name="revoke_file__action">Dosyayı geri çek</string> + <string name="info_row_moderated_at">de yönetildi</string> + <string name="call_connection_via_relay">yönlendirici aracılığıyla</string> + <string name="mark_code_verified">Doğrulanmış olarak işaretle</string> + <string name="connected_to_mobile">Telefona bağlandı</string> + <string name="v5_3_simpler_incognito_mode_descr">Bağlanırken takma ada geçiş yap.</string> + <string name="v5_2_message_delivery_receipts">Mesaj gönderildi!</string> + <string name="update_onion_hosts_settings_question">.onion ana bilgisayarları ayarı güncellensin mi?</string> + <string name="smp_servers_use_server_for_new_conn">Yeni bağlantılar için kullan</string> + <string name="rcv_conn_event_switch_queue_phase_completed">senin için adres değiştirildi</string> + <string name="network_enable_socks">SOCKS vekilini kullan?</string> + <string name="stop_rcv_file__message">Dosya alımı durdurulacak.</string> + <string name="bad_desktop_address">Kötü masaüstü adresi</string> + <string name="revoke_file__title">Dosya geri çekilsin mi?</string> + <string name="la_lock_mode_system">Sistem yetkilendirmesi</string> + <string name="or_scan_qr_code">Veya QR kod okut</string> + <string name="database_migrations">Taşınmalar: %s</string> + <string name="connect_plan_this_is_your_link_for_group_vName"><![CDATA[Bu senin grup için bağlantın! <b>%1$s</b>]]></string> + <string name="unblock_member_confirmation">Engeli kaldır</string> + <string name="icon_descr_asked_to_receive">Fotoğrafı almak için soruldu</string> + <string name="invalid_qr_code">Geçerli olmayan QR kodu</string> + <string name="cannot_access_keychain">Veritabanı şifresini kaydetmek için lazım olan Şifre Yöneticisine erişilemiyor.</string> + <string name="make_private_connection">Gizli bir bağlantı kur</string> + <string name="multicast_discoverable_via_local_network">Yerel ağ üzerinden keşfedilebilir</string> + <string name="info_row_updated_at">Kayıt güncellendi</string> + <string name="smp_servers_use_server">Sunucu kullan</string> + <string name="share_text_received_at">Şuradan alındı: %s</string> + <string name="add_contact_tab">Kişi Ekle</string> + <string name="v5_3_discover_join_groups_descr">- dizin hizmetine bağlan +\n(BETADA!) +\n- çoklu mesaj gönderme +\n(20 kişiye kadar). +\n- daha hızlı ve daha stabil.</string> + <string name="tap_to_scan">Taramak için tıkla</string> + <string name="keep_invitation_link">Tut</string> + <string name="lock_after">Sonra kilitle</string> + <string name="tap_to_paste_link">Bağlantı yapıştırmak için tıkla</string> + <string name="keychain_error">Anahtarlık hatası</string> + <string name="disconnect_desktop_question">Bilgisayarın bağlantısı kesilsin mi?</string> + <string name="loading_remote_file_desc">Bağlantılı telefondan dosya yüklenirken lütfen bekleyin.</string> + <string name="block_member_desc">%s ten gelen bütün yeni mesajlar gizli olacak!</string> + <string name="desktop_app_version_is_incompatible">Masaüstü uygulama versiyonu %s bu uygulama ile uyumlu değil.</string> + <string name="delivery">Gönderim</string> + <string name="no_connected_mobile">Telefona bağlı değil</string> + <string name="search_or_paste_simplex_link">Ara veya SimpleX bağlantısını yapıştır</string> + <string name="info_row_received_at">Şuradan alındı</string> + <string name="accept_feature_set_1_day">1 güne ayarla</string> + <string name="color_received_message">Alınmış mesaj</string> + <string name="rcv_group_event_member_created_contact">doğrudan bağlandı</string> + <string name="blocked_item_description">engellendi</string> </resources> \ No newline at end of file diff --git a/apps/multiplatform/common/src/commonMain/resources/MR/uk/strings.xml b/apps/multiplatform/common/src/commonMain/resources/MR/uk/strings.xml index d9d49aef7d..34ac98e401 100644 --- a/apps/multiplatform/common/src/commonMain/resources/MR/uk/strings.xml +++ b/apps/multiplatform/common/src/commonMain/resources/MR/uk/strings.xml @@ -2,8 +2,8 @@ <resources> <string name="send_disappearing_message_1_minute">1 хвилина</string> <string name="about_simplex">Про SimpleX</string> - <string name="accept_connection_request__question">Прийняти запит на підключення\?</string> - <string name="above_then_preposition_continuation">вище, тоді:</string> + <string name="accept_connection_request__question">Прийняти запит на з\'єднання?</string> + <string name="above_then_preposition_continuation">вище, а потім:</string> <string name="accept_contact_button">Прийняти</string> <string name="accept_call_on_lock_screen">Прийняти</string> <string name="color_primary">Акцент</string> @@ -14,564 +14,561 @@ <string name="accept_feature">Прийняти</string> <string name="send_disappearing_message_5_minutes">5 хвилин</string> <string name="chat_item_ttl_month">1 місяць</string> - <string name="learn_more_about_address">Про адресу SimpleX</string> + <string name="learn_more_about_address">Про SimpleX-адресу</string> <string name="one_time_link_short">1-разове посилання</string> <string name="about_simplex_chat">Про SimpleX Chat</string> - <string name="v4_3_improved_server_configuration_desc">Додайте сервери, відсканувавши QR-коди.</string> - <string name="users_delete_all_chats_deleted">Всі чати та повідомлення будуть видалені - це неможливо скасувати!</string> - <string name="allow_calls_only_if">Дозволяйте дзвінки, тільки якщо ваш контакт дозволяє їх.</string> - <string name="allow_irreversible_message_deletion_only_if">Дозволяйте безповоротне видалення повідомлень, тільки якщо контакт дозволяє вам це зробити.</string> + <string name="v4_3_improved_server_configuration_desc">Додавайте сервери, скануючи QR-коди.</string> + <string name="users_delete_all_chats_deleted">Всі чати і повідомлення будуть видалені - цю дію неможливо скасувати!</string> + <string name="allow_calls_only_if">Дозволяйте дзвінки тільки в разі дозволу вашого контакту.</string> + <string name="allow_irreversible_message_deletion_only_if">Дозволяйте невідворотне видалення повідомлень тільки в разі дозволу вашого контакту.</string> <string name="allow_voice_messages_question">Дозволити голосові повідомлення\?</string> - <string name="app_passcode_replaced_with_self_destruct">Код доступу до програми замінено на пароль самознищення.</string> - <string name="smp_servers_preset_add">Додавання попередньо встановлених серверів</string> - <string name="full_backup">Резервне копіювання даних програми</string> - <string name="smp_servers_add_to_another_device">Додати до іншого пристрою</string> - <string name="keychain_is_storing_securely">Android Keystore використовується для безпечного зберігання парольної фрази - це дозволяє сервісу сповіщень працювати.</string> - <string name="v4_2_group_links_desc">Адміни можуть створювати посилання для приєднання до груп.</string> - <string name="app_version_code">Збірка програми: %s</string> - <string name="allow_voice_messages_only_if">Дозволяйте голосові повідомлення, тільки якщо ваш контакт дозволяє їх.</string> - <string name="allow_to_send_disappearing">Дозволити відправляти зникаючі повідомлення.</string> - <string name="callstatus_accepted">прийнято виклик</string> - <string name="always_use_relay">Завжди використовуйте реле</string> + <string name="app_passcode_replaced_with_self_destruct">Пароль застосунку замінено паролем самознищення.</string> + <string name="smp_servers_preset_add">Додати попередньо встановлені сервери</string> + <string name="full_backup">Резервне копіювання даних застосунку</string> + <string name="smp_servers_add_to_another_device">Додати на інший пристрій</string> + <string name="keychain_is_storing_securely">Сховище ключів Android використовується для безпечного збереження ключової фрази - це дозволяє службі сповіщень працювати.</string> + <string name="v4_2_group_links_desc">Адміністратори можуть створювати посилання для приєднання до групи.</string> + <string name="app_version_code">Збірка додатку: %s</string> + <string name="allow_voice_messages_only_if">Дозволяйте голосові повідомлення тільки в разі дозволу вашого контакту.</string> + <string name="allow_to_send_disappearing">Дозволяйте надсилати повідомлення, які зникають.</string> + <string name="callstatus_accepted">прийнятий виклик</string> + <string name="always_use_relay">Завжди використовувати реле</string> <string name="settings_section_title_app">ДОДАТОК</string> - <string name="allow_direct_messages">Дозволяє надсилати прямі повідомлення користувачам.</string> - <string name="allow_to_delete_messages">Дозволяє безповоротно видаляти надіслані повідомлення.</string> - <string name="allow_to_send_voice">Дозволити надсилати голосові повідомлення.</string> - <string name="allow_message_reactions">Дозволити реакцію на повідомлення.</string> - <string name="v5_1_self_destruct_passcode_descr">Всі дані стираються при введенні.</string> - <string name="v5_0_app_passcode">Пароль додатку</string> - <string name="settings_section_title_icon">ЗНАЧОК ДОДАТКУ</string> - <string name="allow_disappearing_messages_only_if">Дозволяйте зникати повідомленням, тільки якщо ваш контакт дозволяє це робити.</string> + <string name="allow_direct_messages">Дозволяйте надсилати прямі повідомлення учасникам.</string> + <string name="allow_to_delete_messages">Дозволяйте невідворотне видалення відправлених повідомлень.</string> + <string name="allow_to_send_voice">Дозволяйте надсилати голосові повідомлення.</string> + <string name="allow_message_reactions">Дозволити реакції на повідомлення.</string> + <string name="v5_1_self_destruct_passcode_descr">Вся інформація стирається при його введенні.</string> + <string name="v5_0_app_passcode">Пароль для додатка</string> + <string name="settings_section_title_icon">ІКОНКА ДОДАТКУ</string> + <string name="allow_disappearing_messages_only_if">Дозволяйте повідомлення, які зникають, тільки якщо ваш контакт дозволяє їх.</string> <string name="allow_your_contacts_adding_message_reactions">Дозвольте вашим контактам додавати реакції на повідомлення.</string> - <string name="allow_message_reactions_only_if">Дозволяйте реакції на повідомлення, тільки якщо ваш контакт дозволяє їх.</string> - <string name="empty_chat_profile_is_created">Створюється порожній профіль чату з вказаним ім\'ям, і додаток відкривається у звичайному режимі.</string> + <string name="allow_message_reactions_only_if">Дозволяйте реакції на повідомлення тільки в разі дозволу вашого контакту.</string> + <string name="empty_chat_profile_is_created">Створений порожній профіль чату з наданим ім\'ям, і застосунок відкривається, як завжди.</string> <string name="color_primary_variant">Додатковий акцент</string> - <string name="allow_your_contacts_irreversibly_delete">Дозвольте вашим контактам безповоротно видаляти надіслані повідомлення.</string> - <string name="allow_verb">Дозвольте</string> + <string name="allow_your_contacts_irreversibly_delete">Дозвольте вашим контактам невідворотно видаляти відправлені повідомлення.</string> + <string name="allow_verb">Дозволити</string> <string name="network_settings">Розширені налаштування мережі</string> - <string name="network_enable_socks_info">Доступ до серверів через SOCKS проксі на порту %d\? Перед увімкненням цієї опції проксі має бути запущено.</string> - <string name="all_your_contacts_will_remain_connected">Всі ваші контакти залишаться на зв\'язку.</string> - <string name="all_app_data_will_be_cleared">Всі дані програми видаляються.</string> - <string name="keychain_allows_to_receive_ntfs">Android Keystore буде використовуватися для безпечного зберігання пароля після перезапуску програми або зміни пароля - це дозволить отримувати сповіщення.</string> - <string name="allow_your_contacts_to_send_voice_messages">Дозвольте своїм контактам надсилати голосові повідомлення.</string> + <string name="network_enable_socks_info">Отримувати доступ до серверів через SOCKS-проксі на порті %d? Проксі має бути запущено до активації цієї опції.</string> + <string name="all_your_contacts_will_remain_connected">Всі ваші контакти залишаться підключеними.</string> + <string name="all_app_data_will_be_cleared">Всі дані застосунку буде видалено.</string> + <string name="keychain_allows_to_receive_ntfs">Після перезапуску додатка або зміни ключової фрази буде використано сховище ключів Android для безпечного збереження ключової фрази - це дозволить отримувати сповіщення.</string> + <string name="allow_your_contacts_to_send_voice_messages">Дозвольте вашим контактам надсилати голосові повідомлення.</string> <string name="accept_contact_incognito_button">Прийняти інкогніто</string> <string name="smp_servers_add">Додати сервер…</string> - <string name="group_member_role_admin">адмін</string> - <string name="button_add_welcome_message">Додати вітальне повідомлення</string> - <string name="all_group_members_will_remain_connected">Всі учасники групи залишаться на зв\'язку.</string> - <string name="allow_your_contacts_to_send_disappearing_messages">Дозвольте своїм контактам надсилати зникаючі повідомлення.</string> - <string name="clear_chat_warning">Всі повідомлення будуть видалені - це неможливо скасувати! Повідомлення будуть видалені ТІЛЬКИ для вас.</string> - <string name="app_version_title">Версія програми</string> - <string name="add_address_to_your_profile">Додайте адресу до свого профілю, щоб ваші контакти могли поділитися нею з іншими людьми. Повідомлення про оновлення профілю буде надіслано вашим контактам.</string> - <string name="all_your_contacts_will_remain_connected_update_sent">Всі ваші контакти залишаться на зв\'язку. Повідомлення про оновлення профілю буде надіслано вашим контактам.</string> - <string name="answer_call">Відповісти на дзвінок</string> + <string name="group_member_role_admin">адміністратор</string> + <string name="button_add_welcome_message">Додати привітання</string> + <string name="all_group_members_will_remain_connected">Всі члени групи залишаться підключеними.</string> + <string name="allow_your_contacts_to_send_disappearing_messages">Дозвольте вашим контактам надсилати повідомлення, які зникають.</string> + <string name="clear_chat_warning">Всі повідомлення будуть видалені - цю дію неможливо скасувати! Повідомлення будуть видалені ЛИШЕ для вас.</string> + <string name="app_version_title">Версія додатку</string> + <string name="add_address_to_your_profile">Додайте адресу до свого профілю, щоб ваші контакти могли поділитися нею з іншими людьми. Оновлення профілю буде відправлено вашим контактам.</string> + <string name="all_your_contacts_will_remain_connected_update_sent">Всі ваші контакти залишаться підключеними. Оновлення профілю буде відправлено вашим контактам.</string> + <string name="answer_call">Відповісти на виклик</string> <string name="address_section_title">Адреса</string> <string name="users_add">Додати профіль</string> - <string name="color_secondary_variant">Додатковий вторинний</string> - <string name="notifications_mode_service">Завжди увімкнено</string> - <string name="notifications_mode_off_desc">Додаток може отримувати сповіщення лише під час роботи, жодні фонові служби не запускаються</string> + <string name="color_secondary_variant">Додатковий другорядний</string> + <string name="notifications_mode_service">Завжди включено</string> + <string name="notifications_mode_off_desc">Додаток може отримувати сповіщення тільки тоді, коли він працює, фоновий сервіс не буде запущено</string> <string name="chat_preferences_always">завжди</string> - <string name="allow_your_contacts_to_call">Дозвольте вашим контактам телефонувати вам.</string> - <string name="network_session_mode_user_description"><![CDATA[<b>Для кожного профілю чату, який ви маєте в додатку</b>, буде використовуватися окреме TCP-з\'єднання (і SOCKS-обліковий запис).]]></string> - <string name="appearance_settings">Зовнішній вигляд</string> - <string name="app_version_name">Версія програми: v%s</string> - <string name="network_session_mode_entity_description"><b>Для кожного контакту і члена групи</b> буде використовуватися окреме TCP-з\'єднання (і SOCKS-обліковий запис). -\n<b>Зверніть увагу</b>: якщо у вас багато з\'єднань, споживання заряду акумулятора і трафіку може бути значно вищим, а деякі з\'єднання можуть обірватися.</string> - <string name="turning_off_service_and_periodic">Активна оптимізація заряду батареї, яка вимикає фоновий сервіс і періодичні запити на нові повідомлення. Ви можете знову увімкнути їх через налаштування.</string> + <string name="allow_your_contacts_to_call">Дозвольте вашим контактам дзвонити вам.</string> + <string name="network_session_mode_user_description"><![CDATA[Окреме TCP-підключення (і обліковий запис SOCKS) буде використовуватися <b>для кожного профілю чату, який у вас є в додатку</b>.]]></string> + <string name="appearance_settings">Вигляд</string> + <string name="app_version_name">Версія додатку: v%s</string> + <string name="network_session_mode_entity_description">Окреме TCP-підключення (і обліковий запис SOCKS) буде використовуватися <b>для кожного контакту та учасника групи</b>. +\n<b>Зверніть увагу</b>: якщо у вас багато підключень, споживання заряду батареї та трафіку може значно збільшитися, і деякі підключення можуть бути невдалими.</string> + <string name="turning_off_service_and_periodic">Активована оптимізація батареї, вимикається фоновий сервіс і періодичні запити нових повідомлень. Ви можете знову увімкнути їх у налаштуваннях.</string> <string name="back">Назад</string> <string name="bold_text">жирний</string> - <string name="onboarding_notifications_mode_periodic_desc"><![CDATA[<b>Корисно для батареї</b>. Фонова служба перевіряє повідомлення кожні 10 хвилин. Ви можете пропустити дзвінки або термінові повідомлення.]]></string> - <string name="settings_audio_video_calls">Аудіо та відео виклики</string> - <string name="icon_descr_audio_off">Звук вимкнено</string> - <string name="auth_unavailable">Автентифікація недоступна</string> - <string name="icon_descr_video_asked_to_receive">Попросили отримати відео</string> - <string name="v4_2_auto_accept_contact_requests">Автоматичне прийняття запитів на контакт</string> + <string name="onboarding_notifications_mode_periodic_desc"><![CDATA[<b>Добре для акумулятора</b>. Сервіс фонового запуску перевіряє повідомлення кожні 10 хвилин. Ви можете пропустити виклики чи важливі повідомлення.]]></string> + <string name="settings_audio_video_calls">Аудіо та відеовиклики</string> + <string name="icon_descr_audio_off">Аудіо вимкнено</string> + <string name="auth_unavailable">Аутентифікація недоступна</string> + <string name="icon_descr_video_asked_to_receive">Запит на отримання відео</string> + <string name="v4_2_auto_accept_contact_requests">Автоприйняття запитів на контакт</string> <string name="audio_call_no_encryption">аудіовиклик (не зашифрований e2e)</string> - <string name="both_you_and_your_contacts_can_delete">І ви, і ваш контакт можете безповоротно видалити надіслані повідомлення.</string> + <string name="both_you_and_your_contacts_can_delete">Як ви, так і ваш контакт можете невідворотно видаляти відправлені повідомлення.</string> <string name="alert_title_msg_bad_hash">Поганий хеш повідомлення</string> <string name="alert_title_msg_bad_id">Неправильний ідентифікатор повідомлення</string> - <string name="auto_accept_images">Автоматичне прийняття зображень</string> + <string name="auto_accept_images">Автоматично приймати зображення</string> <string name="v5_1_better_messages">Кращі повідомлення</string> - <string name="icon_descr_audio_on">Звук увімкнено</string> - <string name="both_you_and_your_contact_can_add_message_reactions">Реакції на повідомлення можете додавати як ви, так і ваш контакт.</string> + <string name="icon_descr_audio_on">Аудіо увімкнено</string> + <string name="both_you_and_your_contact_can_add_message_reactions">Як ви, так і ваш контакт можуть додавати реакції на повідомлення.</string> <string name="icon_descr_audio_call">аудіовиклик</string> - <string name="onboarding_notifications_mode_off_desc"><![CDATA[<b>Найкраще для батареї</b>. Ви отримуватимете сповіщення лише тоді, коли додаток працює (БЕЗ фонового сервісу).]]></string> - <string name="v4_6_audio_video_calls">Аудіо та відеодзвінки</string> - <string name="la_authenticate">Автентифікація</string> - <string name="la_auth_failed">Не вдалося пройти автентифікацію</string> - <string name="authentication_cancelled">Аутентифікацію скасовано</string> - <string name="auto_accept_contact">Автоприйняття</string> + <string name="onboarding_notifications_mode_off_desc"><![CDATA[<b>Найкраще для акумулятора</b>. Ви отримуєте сповіщення тільки тоді, коли додаток працює (НЕТЛЕ фоновий сервіс).]]></string> + <string name="v4_6_audio_video_calls">Аудіо та відеовиклики</string> + <string name="la_authenticate">Аутентифікація</string> + <string name="la_auth_failed">Помилка аутентифікації</string> + <string name="authentication_cancelled">Аутентифікація відмінена</string> + <string name="auto_accept_contact">Автоприйом</string> <string name="integrity_msg_bad_hash">поганий хеш повідомлення</string> - <string name="integrity_msg_bad_id">помилковий ідентифікатор повідомлення</string> + <string name="integrity_msg_bad_id">поганий ідентифікатор повідомлення</string> <string name="color_background">Фон</string> - <string name="add_new_contact_to_create_one_time_QR_code"><![CDATA[<b>Додайте новий контакт</b>: для створення одноразового QR-коду для вашого контакту.]]></string> - <string name="it_can_disabled_via_settings_notifications_still_shown"><![CDATA[<b>Його можна вимкнути в налаштуваннях</b> - сповіщення все одно будуть показуватися під час роботи програми.]]></string> - <string name="notifications_mode_service_desc">Фоновий сервіс працює постійно - сповіщення з\'являтимуться, щойно повідомлення стануть доступними.</string> - <string name="icon_descr_asked_to_receive">Попросили отримати зображення</string> + <string name="it_can_disabled_via_settings_notifications_still_shown">Це можна вимкнути у налаштуваннях – сповіщення все одно будуть відображатися, коли програма працює.</string> + <string name="notifications_mode_service_desc">Служба фонового режиму завжди активна – сповіщення відображатимуться, як тільки повідомлення будуть доступні.</string> + <string name="icon_descr_asked_to_receive">Запит на отримання зображення</string> <string name="attach">Прикріпити</string> <string name="audio_video_calls">Аудіо/відео дзвінки</string> <string name="available_in_v51">" -\nДоступно у v5.1"</string> +\nДоступно в версії 5.1"</string> <string name="calls_prohibited_with_this_contact">Аудіо/відео дзвінки заборонені.</string> <string name="app_name">SimpleX</string> - <string name="both_you_and_your_contact_can_make_calls">Дзвонити можете як ви, так і ваш контакт.</string> - <string name="thousand_abbreviation">k</string> - <string name="connect_via_contact_link">Підключитися через контактну адресу?</string> - <string name="connect_via_invitation_link">Підключитися за одноразовим посиланням?</string> + <string name="both_you_and_your_contact_can_make_calls">Як ви, так і ваш контакт можуть здійснювати дзвінки.</string> + <string name="thousand_abbreviation">тис.</string> + <string name="connect_via_contact_link">Підключитися через адресу контакту?</string> + <string name="connect_via_invitation_link">Підключитися через одноразове посилання?</string> <string name="connect_via_group_link">Приєднатися до групи?</string> - <string name="profile_will_be_sent_to_contact_sending_link">Ваш профіль буде надіслано контакту, від якого ви отримали це посилання.</string> - <string name="you_will_join_group">Ви з\'єднаєтеся з усіма учасниками групи.</string> - <string name="connect_via_link_verb">Підключіться</string> - <string name="server_connected">підключений</string> + <string name="profile_will_be_sent_to_contact_sending_link">Ваш профіль буде відправлено контакту, з якого ви отримали це посилання.</string> + <string name="you_will_join_group">Ви приєднаєтеся до всіх учасників групи.</string> + <string name="connect_via_link_verb">Підключити</string> + <string name="server_connected">підключено</string> <string name="server_error">помилка</string> <string name="server_connecting">підключення</string> - <string name="connected_to_server_to_receive_messages_from_contact">Ви підключені до сервера, який використовується для отримання повідомлень від цього контакту.</string> - <string name="trying_to_connect_to_server_to_receive_messages_with_error">Спроба з\'єднатися з сервером, який використовується для отримання повідомлень від цього контакту (помилка: %1$s ).</string> + <string name="connected_to_server_to_receive_messages_from_contact">Ви підключені до сервера для отримання повідомлень від цього контакту.</string> + <string name="trying_to_connect_to_server_to_receive_messages_with_error">Спроба підключитися до сервера для отримання повідомлень від цього контакту (помилка: %1$s).</string> <string name="deleted_description">видалено</string> - <string name="trying_to_connect_to_server_to_receive_messages">Спроба з\'єднатися з сервером, який використовується для отримання повідомлень від цього контакту.</string> - <string name="marked_deleted_description">з позначкою видалено</string> - <string name="moderated_item_description">модерується %s</string> + <string name="trying_to_connect_to_server_to_receive_messages">Спроба підключитися до сервера для отримання повідомлень від цього контакту.</string> + <string name="marked_deleted_description">відзначено як видалено</string> + <string name="moderated_item_description">модеровано %s</string> <string name="sending_files_not_yet_supported">надсилання файлів поки що не підтримується</string> - <string name="receiving_files_not_yet_supported">отримання файлів поки що не підтримується</string> + <string name="receiving_files_not_yet_supported">приймання файлів поки що не підтримується</string> <string name="sender_you_pronoun">ви</string> <string name="unknown_message_format">невідомий формат повідомлення</string> - <string name="invalid_message_format">невірний формат повідомлення</string> - <string name="live">НАЖИВО</string> - <string name="moderated_description">модерується</string> - <string name="invalid_chat">недійсний чат</string> - <string name="invalid_data">невірні дані</string> - <string name="display_name_connection_established">з\'єднання встановлено</string> - <string name="display_name_invited_to_connect">запрошено до підключення</string> + <string name="invalid_message_format">неправильний формат повідомлення</string> + <string name="live">LIVE</string> + <string name="moderated_description">модеровано</string> + <string name="invalid_chat">неправильний чат</string> + <string name="invalid_data">неправильні дані</string> + <string name="display_name_connection_established">підключення встановлено</string> + <string name="display_name_invited_to_connect">запрошення на підключення</string> <string name="display_name_connecting">підключення…</string> <string name="description_you_shared_one_time_link">ви поділилися одноразовим посиланням</string> - <string name="description_you_shared_one_time_link_incognito">ви поділилися одноразовим посиланням анонімно</string> - <string name="description_via_group_link">через групове посилання</string> - <string name="description_via_group_link_incognito">інкогніто через групове посилання</string> - <string name="description_via_contact_address_link">за посиланням на контактну адресу</string> - <string name="description_via_contact_address_link_incognito">інкогніто за посиланням на контактну адресу</string> - <string name="description_via_one_time_link">за одноразовим посиланням</string> - <string name="description_via_one_time_link_incognito">інкогніто за одноразовим посиланням</string> - <string name="simplex_link_contact">Контактна адреса SimpleX</string> - <string name="simplex_link_invitation">Одноразове запрошення SimpleX</string> - <string name="simplex_link_group">Посилання на групу SimpleX</string> + <string name="description_you_shared_one_time_link_incognito">ви поділилися одноразовим посиланням в інкогніто</string> + <string name="description_via_group_link">через посилання групи</string> + <string name="description_via_group_link_incognito">інкогніто через посилання групи</string> + <string name="description_via_contact_address_link">через посилання адреси контакту</string> + <string name="description_via_contact_address_link_incognito">інкогніто через посилання адреси контакту</string> + <string name="description_via_one_time_link">через одноразове посилання</string> + <string name="description_via_one_time_link_incognito">інкогніто через одноразове посилання</string> + <string name="simplex_link_contact">Адреса контакту у SimpleX</string> + <string name="simplex_link_invitation">Одноразове запрошення у SimpleX</string> + <string name="simplex_link_group">Посилання на групу у SimpleX</string> <string name="simplex_link_connection">через %1$s</string> <string name="simplex_link_mode">Посилання SimpleX</string> <string name="simplex_link_mode_description">Опис</string> <string name="simplex_link_mode_full">Повне посилання</string> <string name="simplex_link_mode_browser">Через браузер</string> - <string name="simplex_link_mode_browser_warning">Відкриття посилання в браузері може знизити конфіденційність і безпеку з\'єднання. Ненадійні посилання SimpleX будуть червоного кольору.</string> + <string name="simplex_link_mode_browser_warning">Відкриття посилання в браузері може зменшити конфіденційність та безпеку з\'єднання. Ненадійні посилання SimpleX будуть виділені червоним кольором.</string> <string name="failed_to_parse_chats_title">Не вдалося завантажити чати</string> - <string name="error_saving_smp_servers">Помилка збереження SMP-серверів</string> - <string name="ensure_smp_server_address_are_correct_format_and_unique">Переконайтеся, що адреси SMP-серверів мають правильний формат, розділені рядками і не дублюються.</string> + <string name="error_saving_smp_servers">Помилка збереження серверів SMP</string> + <string name="ensure_smp_server_address_are_correct_format_and_unique">Переконайтеся, що адреси серверів SMP вірного формату, розділені переносами рядків і не дублюються.</string> <string name="error_setting_network_config">Помилка оновлення конфігурації мережі</string> <string name="failed_to_parse_chat_title">Не вдалося завантажити чат</string> - <string name="contact_developers">Будь ласка, оновіть додаток та зв\'яжіться з розробниками.</string> - <string name="failed_to_create_user_title">Помилка при створенні профілю!</string> - <string name="failed_to_create_user_duplicate_desc">Ви вже маєте профіль у чаті з таким самим іменем. Будь ласка, виберіть інше ім\'я.</string> - <string name="failed_to_active_user_title">Помилка перемикання профілю!</string> - <string name="connection_timeout">Тайм-аут з\'єднання</string> + <string name="contact_developers">Будь ласка, оновіть додаток і зверніться до розробників.</string> + <string name="failed_to_create_user_title">Помилка створення профілю!</string> + <string name="failed_to_create_user_duplicate_desc">Ви вже маєте профіль чату з таким самим ім\'ям відображення. Будь ласка, виберіть інше ім\'я.</string> + <string name="failed_to_active_user_title">Помилка переключення профілю!</string> + <string name="connection_timeout">Тайм-аут підключення</string> <string name="connection_error">Помилка підключення</string> - <string name="network_error_desc">Будь ласка, перевірте своє мережеве з\'єднання за допомогою %1$s і спробуйте ще раз.</string> + <string name="network_error_desc">Будь ласка, перевірте ваше мережеве підключення з %1$s та спробуйте ще раз.</string> <string name="contact_already_exists">Контакт вже існує</string> <string name="connection_error_auth">Помилка підключення (AUTH)</string> - <string name="sender_may_have_deleted_the_connection_request">Можливо, відправник видалив запит на підключення.</string> + <string name="sender_may_have_deleted_the_connection_request">Відправник, можливо, видалив запит на з\'єднання.</string> <string name="error_deleting_contact_request">Помилка видалення запиту на контакт</string> <string name="error_changing_address">Помилка зміни адреси</string> - <string name="error_smp_test_failed_at_step">Помилка тесту на кроці %s.</string> + <string name="error_smp_test_failed_at_step">Тест не пройшов на кроці %s.</string> <string name="error_smp_test_server_auth">Сервер вимагає авторизації для створення черг, перевірте пароль</string> - <string name="error_smp_test_certificate">Можливо, в адресі сервера неправильно вказано відбиток сертифіката</string> + <string name="error_smp_test_certificate">Можливо, відбиток цифрового підпису сертифіката в адресі сервера невірний</string> <string name="smp_server_test_create_queue">Створити чергу</string> <string name="service_notifications">Миттєві сповіщення!</string> <string name="service_notifications_disabled">Миттєві сповіщення вимкнено!</string> <string name="simplex_service_notification_text">Отримання повідомлень…</string> - <string name="hide_notification">Приховати</string> - <string name="ntf_channel_messages">Повідомлення SimpleX Chat</string> - <string name="notification_preview_mode_contact_desc">Показати тільки контакт</string> + <string name="hide_notification">Сховати</string> + <string name="ntf_channel_messages">Повідомлення чату SimpleX</string> + <string name="notification_preview_mode_contact_desc">Показати лише контакт</string> <string name="notification_new_contact_request">Новий запит на контакт</string> <string name="notification_contact_connected">Підключено</string> - <string name="auth_simplex_lock_turned_on">SimpleX Lock увімкнено</string> + <string name="auth_simplex_lock_turned_on">Блокування SimpleX увімкнено</string> <string name="auth_unlock">Розблокувати</string> - <string name="auth_disable_simplex_lock">Вимкнути SimpleX Lock</string> + <string name="auth_disable_simplex_lock">Вимкнути блокування SimpleX</string> <string name="reply_verb">Відповісти</string> <string name="save_verb">Зберегти</string> <string name="delete_verb">Видалити</string> - <string name="delete_message_mark_deleted_warning">Повідомлення буде позначено для видалення. Отримувач(и) зможуть відкрити це повідомлення.</string> - <string name="delete_member_message__question">Видалити повідомлення користувача\?</string> - <string name="for_me_only">Видалити для мене</string> + <string name="delete_message_mark_deleted_warning">Повідомлення буде позначено для видалення. Однак одержувач(і) зможуть розкрити це повідомлення.</string> + <string name="delete_member_message__question">Видалити повідомлення учасника?</string> + <string name="for_me_only">Видалити лише для мене</string> <string name="for_everybody">Для всіх</string> - <string name="icon_descr_edited">відредаговано</string> - <string name="icon_descr_sent_msg_status_send_failed">не вдалося відправити</string> - <string name="icon_descr_received_msg_status_unread">не прочитано</string> + <string name="icon_descr_edited">редаговано</string> + <string name="icon_descr_sent_msg_status_send_failed">помилка відправки</string> + <string name="icon_descr_received_msg_status_unread">непрочитане</string> <string name="group_preview_join_as">приєднатися як %s</string> <string name="icon_descr_cancel_image_preview">Скасувати попередній перегляд зображення</string> <string name="icon_descr_cancel_file_preview">Скасувати попередній перегляд файлу</string> - <string name="icon_descr_waiting_for_image">Очікування зображення</string> - <string name="icon_descr_image_snd_complete">Зображення надіслано</string> - <string name="waiting_for_image">Очікування зображення</string> + <string name="icon_descr_waiting_for_image">Очікування на зображення</string> + <string name="icon_descr_image_snd_complete">Зображення відправлене</string> + <string name="waiting_for_image">Очікування на зображення</string> <string name="large_file">Великий файл!</string> <string name="file_saved">Файл збережено</string> <string name="voice_message">Голосове повідомлення</string> <string name="voice_message_send_text">Голосове повідомлення…</string> - <string name="delete_contact_all_messages_deleted_cannot_undo_warning">Контакт і всі повідомлення будуть видалені - це неможливо скасувати!</string> - <string name="icon_descr_server_status_pending">В очікуванні</string> - <string name="switch_receiving_address_question">Змінити адресу отримання\?</string> + <string name="delete_contact_all_messages_deleted_cannot_undo_warning">Контакт і всі повідомлення будуть видалені - цього не можна скасувати!</string> + <string name="icon_descr_server_status_pending">Очікує</string> + <string name="switch_receiving_address_question">Змінити адресу для отримання?</string> <string name="view_security_code">Переглянути код безпеки</string> - <string name="you_need_to_allow_to_send_voice">Щоб мати змогу надсилати голосові повідомлення, вам потрібно дозволити контакту надсилати їх.</string> + <string name="you_need_to_allow_to_send_voice">Ви повинні дозволити вашому контакту надсилати голосові повідомлення, щоб мати змогу надсилати їх.</string> <string name="cancel_verb">Скасувати</string> - <string name="ok">ГАРАЗД</string> + <string name="ok">OK</string> <string name="copied">Скопійовано в буфер обміну</string> - <string name="to_connect_via_link_title">Підключитися за посиланням</string> - <string name="mobile_tap_open_in_mobile_app_then_tap_connect_in_app"><![CDATA[📱 мобільний: торкніться <b>Відкрийте в мобільному додатку</b>, потім торкніться <b>Підключіть</b> в додатку.]]></string> - <string name="mute_chat">Вимкнути звук</string> - <string name="unmute_chat">Увімкнути звук</string> - <string name="you_invited_a_contact">Ви запросили свого контакта</string> - <string name="contact_you_shared_link_with_wont_be_able_to_connect">Контакт, якому ви надали це посилання, НЕ зможе підключитися!</string> + <string name="to_connect_via_link_title">Для підключення через посилання</string> + <string name="mobile_tap_open_in_mobile_app_then_tap_connect_in_app"><![CDATA[📱 мобільний телефон: натисніть <b>Відкрити у мобільному додатку</b>, а потім торкніться <b>Підключити</b> в додатку.]]></string> + <string name="mute_chat">Приглушити</string> + <string name="unmute_chat">Скасувати приглушення</string> + <string name="you_invited_a_contact">Ви запросили контакт</string> + <string name="contact_you_shared_link_with_wont_be_able_to_connect">Контакт, якому ви поділилися посиланням, НЕ зможе підключитися!</string> <string name="icon_descr_profile_image_placeholder">заповнювач зображення профілю</string> <string name="image_descr_qr_code">QR-код</string> - <string name="icon_descr_help">допомога</string> - <string name="if_you_cannot_meet_in_person_show_QR_in_video_call_or_via_another_channel"><![CDATA[Якщо ви не можете зустрітися особисто, <b>покажіть QR-код у відеодзвінку</b> або поділіться посиланням.]]></string> - <string name="your_chat_profile_will_be_sent_to_your_contact">Ваш профіль чату буде надіслано -\nдо вашого контакту</string> - <string name="one_time_link">Посилання на одноразове запрошення</string> - <string name="incorrect_code">Неправильний код безпеки!</string> - <string name="to_verify_compare">Щоб перевірити наскрізне шифрування з вашим контактом, порівняйте (або відскануйте) код на ваших пристроях.</string> + <string name="icon_descr_help">довідка</string> + <string name="if_you_cannot_meet_in_person_show_QR_in_video_call_or_via_another_channel"><![CDATA[Якщо ви не можете зустрітися особисто, <b>покажіть QR-код у відеовиклику</b>, або поділіться посиланням.]]></string> + <string name="your_chat_profile_will_be_sent_to_your_contact">Ваш профіль чату буде відправлено +\nвашому контакту</string> + <string name="one_time_link">Одноразове запрошення</string> + <string name="incorrect_code">Невірний код безпеки!</string> + <string name="to_verify_compare">Для перевірки end-to-end шифрування порівняйте (або скануйте) код на своїх пристроях.</string> <string name="your_settings">Ваші налаштування</string> - <string name="your_simplex_contact_address">Ваша адреса SimpleX</string> - <string name="markdown_help">Допомога з уцінкою</string> - <string name="chat_lock">SimpleX Lock</string> + <string name="your_simplex_contact_address">Ваша SimpleX-адреса</string> + <string name="markdown_help">Допомога з Markdown</string> + <string name="chat_lock">Блокування SimpleX</string> <string name="chat_console">Консоль чату</string> <string name="smp_servers">Сервери SMP</string> - <string name="smp_servers_scan_qr">Відскануйте QR-код сервера</string> - <string name="smp_servers_use_server_for_new_conn">Використовуйте для нових з\'єднань</string> + <string name="smp_servers_scan_qr">Сканувати QR-код сервера</string> + <string name="smp_servers_use_server_for_new_conn">Використовувати для нових підключень</string> <string name="smp_servers_delete_server">Видалити сервер</string> - <string name="star_on_github">Зірка на GitHub</string> - <string name="how_to_use_your_servers">Як користуватися вашими серверами</string> - <string name="saved_ICE_servers_will_be_removed">Збережені сервери WebRTC ICE буде видалено.</string> - <string name="configure_ICE_servers">Налаштування серверів ICE</string> + <string name="star_on_github">Оцінити на GitHub</string> + <string name="how_to_use_your_servers">Як використовувати ваші сервери</string> + <string name="saved_ICE_servers_will_be_removed">Збережені сервери WebRTC ICE будуть видалені.</string> + <string name="configure_ICE_servers">Налаштувати сервери ICE</string> <string name="network_and_servers">Мережа та сервери</string> <string name="network_settings_title">Налаштування мережі</string> - <string name="network_enable_socks">Використовувати SOCKS проксі\?</string> - <string name="network_disable_socks">Використовуєте пряме підключення до Інтернету\?</string> - <string name="update_onion_hosts_settings_question">Оновити налаштування хостів .onion\?</string> - <string name="network_use_onion_hosts">Використовуйте хости .onion</string> - <string name="network_use_onion_hosts_prefer">При наявності</string> + <string name="network_enable_socks">Використовувати SOCKS-проксі?</string> + <string name="network_disable_socks">Використовувати прямий підключення до Інтернету?</string> + <string name="update_onion_hosts_settings_question">Оновити налаштування .onion-хостів?</string> + <string name="network_use_onion_hosts">Використовувати .onion-хости</string> + <string name="network_use_onion_hosts_prefer">Якщо доступно</string> <string name="network_use_onion_hosts_no">Ні</string> - <string name="network_use_onion_hosts_prefer_desc">Onion хости будуть використовуватися за наявності.</string> - <string name="update_network_session_mode_question">Оновити режим транспортної ізоляції\?</string> + <string name="network_use_onion_hosts_prefer_desc">.Onion-хости будуть використовуватися, якщо доступні.</string> + <string name="update_network_session_mode_question">Оновити режим ізоляції транспорту?</string> <string name="core_simplexmq_version">simplexmq: v%s (%2s)</string> <string name="create_address">Створити адресу</string> - <string name="share_link">Поділіться посиланням</string> + <string name="share_link">Поділитися посиланням</string> <string name="delete_address">Видалити адресу</string> <string name="full_name__field">Повне ім\'я:</string> <string name="you_control_your_chat">Ви керуєте своїм чатом!</string> - <string name="the_messaging_and_app_platform_protecting_your_privacy_and_security">Платформа для обміну повідомленнями та додатків, що захищає вашу конфіденційність і безпеку.</string> + <string name="the_messaging_and_app_platform_protecting_your_privacy_and_security">Платформа обміну повідомленнями і застосунок, які захищають вашу конфіденційність та безпеку.</string> <string name="display_name">Введіть своє ім\'я:</string> - <string name="callstatus_in_progress">виклик у процесі</string> - <string name="callstate_starting">починаючи…</string> - <string name="first_platform_without_user_ids">Перша платформа без жодних ідентифікаторів користувачів – приватна за дизайном.</string> - <string name="decentralized">Децентралізований</string> - <string name="use_chat">Використовуйте чат</string> - <string name="onboarding_notifications_mode_subtitle">Пізніше його можна змінити через налаштування.</string> + <string name="callstatus_in_progress">дзвінок в процесі</string> + <string name="callstate_starting">запуск…</string> + <string name="first_platform_without_user_ids">Перша платформа без ідентифікаторів користувачів – приватна за конструкцією.</string> + <string name="decentralized">Децентралізована</string> + <string name="use_chat">Використовувати чат</string> + <string name="onboarding_notifications_mode_subtitle">Це можна змінити пізніше в налаштуваннях.</string> <string name="onboarding_notifications_mode_service">Миттєво</string> - <string name="call_already_ended">Дзвінок вже закінчився!</string> - <string name="your_calls">Ваші дзвінки</string> + <string name="call_already_ended">Виклик вже завершено!</string> + <string name="your_calls">Ваші виклики</string> <string name="your_ice_servers">Ваші сервери ICE</string> <string name="open_verb">Відкрити</string> <string name="call_connection_via_relay">через реле</string> <string name="icon_descr_speaker_on">Динамік увімкнено</string> - <string name="icon_descr_flip_camera">Перевернути камеру</string> - <string name="icon_descr_call_rejected">Відхилений дзвінок</string> - <string name="integrity_msg_skipped">%1$d пропущено повідомлення(і)</string> + <string name="icon_descr_flip_camera">Повернути камеру</string> + <string name="icon_descr_call_rejected">Відхилений виклик</string> + <string name="integrity_msg_skipped">%1$d пропущено повідомлень</string> <string name="settings_section_title_chats">ЧАТИ</string> - <string name="settings_section_title_socks">SOCKS PROXY</string> - <string name="error_starting_chat">Помилка запуску чату</string> + <string name="settings_section_title_socks">SOCKS-ПРОКСІ</string> + <string name="error_starting_chat">Помилка при запуску чату</string> <string name="stop_chat_confirmation">Зупинити</string> - <string name="import_database_confirmation">Імпорт</string> + <string name="import_database_confirmation">Імпортувати</string> <string name="files_and_media_section">Файли та медіа</string> <string name="messages_section_title">Повідомлення</string> - <string name="error_changing_message_deletion">Налаштування зміни помилки</string> + <string name="error_changing_message_deletion">Помилка зміни налаштувань</string> <string name="database_encrypted">База даних зашифрована!</string> - <string name="new_passphrase">Новий пароль…</string> - <string name="confirm_new_passphrase">Підтвердіть нову парольну фразу…</string> + <string name="new_passphrase">Нова ключова фраза…</string> + <string name="confirm_new_passphrase">Підтвердіть нову ключову фразу…</string> <string name="encrypt_database_question">Зашифрувати базу даних\?</string> - <string name="wrong_passphrase_title">Неправильна парольна фраза!</string> - <string name="enter_correct_passphrase">Введіть правильну парольну фразу.</string> + <string name="wrong_passphrase_title">Неправильна ключова фраза!</string> + <string name="enter_correct_passphrase">Введіть правильну ключову фразу.</string> <string name="chat_archive_header">Архів чату</string> <string name="chat_archive_section">АРХІВ ЧАТУ</string> - <string name="rcv_group_event_member_connected">підключений</string> - <string name="rcv_group_event_changed_your_role">змінив свою роль на %s</string> - <string name="snd_group_event_changed_role_for_yourself">ви змінили роль для себе на %s</string> + <string name="rcv_group_event_member_connected">підключив(лась)</string> + <string name="rcv_group_event_changed_your_role">змінив(ла) вашу роль на %s</string> + <string name="snd_group_event_changed_role_for_yourself">ви змінили свою роль на %s</string> <string name="snd_conn_event_switch_queue_phase_completed">ви змінили адресу</string> - <string name="no_contacts_selected">Не вибрано жодного контакту</string> + <string name="no_contacts_selected">Не вибрано контактів</string> <string name="delete_group_question">Видалити групу\?</string> - <string name="remove_member_confirmation">Видалити</string> + <string name="remove_member_confirmation">Вилучити</string> <string name="info_row_connection">Підключення</string> - <string name="conn_level_desc_direct">прямий</string> - <string name="update_network_settings_confirmation">Оновлення</string> + <string name="conn_level_desc_direct">пряме</string> + <string name="update_network_settings_confirmation">Оновити</string> <string name="chat_preferences_contact_allows">Контакт дозволяє</string> <string name="chat_preferences">Налаштування чату</string> - <string name="prohibit_sending_disappearing_messages">Заборонити надсилання зникаючих повідомлень.</string> - <string name="prohibit_sending_voice_messages">Заборонити надсилання голосових повідомлень.</string> + <string name="prohibit_sending_disappearing_messages">Заборонити надсилання повідомлень, які зникають.</string> + <string name="prohibit_sending_voice_messages">Забороняйте надсилання голосових повідомлень.</string> <string name="v4_4_french_interface">Французький інтерфейс</string> - <string name="error_saving_xftp_servers">Помилка збереження XFTP-серверів</string> - <string name="ensure_xftp_server_address_are_correct_format_and_unique">Переконайтеся, що адреси XFTP-серверів мають правильний формат, розділені рядками і не дублюються.</string> - <string name="error_loading_xftp_servers">Помилка завантаження XFTP-серверів</string> - <string name="error_adding_members">Помилка додавання користувача(ів)</string> + <string name="error_saving_xftp_servers">Помилка збереження серверів XFTP</string> + <string name="ensure_xftp_server_address_are_correct_format_and_unique">Переконайтеся, що адреси серверів XFTP вірного формату, розділені переносами рядків і не дублюються.</string> + <string name="error_loading_xftp_servers">Помилка завантаження серверів XFTP</string> + <string name="error_adding_members">Помилка додавання учасників</string> <string name="error_joining_group">Помилка приєднання до групи</string> - <string name="cannot_receive_file">Не вдається отримати файл</string> + <string name="cannot_receive_file">Неможливо отримати файл</string> <string name="smp_server_test_compare_file">Порівняти файл</string> <string name="smp_server_test_delete_file">Видалити файл</string> <string name="periodic_notifications_disabled">Періодичні сповіщення вимкнено!</string> - <string name="enter_passphrase_notification_title">Потрібна парольна фраза</string> + <string name="enter_passphrase_notification_title">Потрібен пароль</string> <string name="la_notice_turn_on">Увімкнути</string> - <string name="auth_device_authentication_is_not_enabled_you_can_turn_on_in_settings_once_enabled">Автентифікація пристрою не ввімкнена. Ви можете увімкнути SimpleX Lock у Налаштуваннях, коли увімкнете автентифікацію пристрою.</string> - <string name="auth_device_authentication_is_disabled_turning_off">Автентифікацію пристрою вимкнено. Вимкнення SimpleX Lock.</string> + <string name="auth_device_authentication_is_not_enabled_you_can_turn_on_in_settings_once_enabled">Аутентифікація пристрою не увімкнена. Ви можете увімкнути блокування SimpleX через налаштування, якщо увімкнете аутентифікацію пристрою.</string> + <string name="auth_device_authentication_is_disabled_turning_off">Аутентифікація пристрою вимкнена. Вимикається блокування SimpleX.</string> <string name="auth_stop_chat">Зупинити чат</string> - <string name="auth_open_chat_console">Відкрийте консоль чату</string> + <string name="auth_open_chat_console">Відкрити консоль чату</string> <string name="moderate_message_will_be_marked_warning">Повідомлення буде позначено як модероване для всіх учасників.</string> <string name="your_chats">Чати</string> <string name="contact_connection_pending">підключення…</string> <string name="group_connection_pending">підключення…</string> - <string name="tap_to_start_new_chat">Натисніть, щоб почати новий чат</string> - <string name="chat_with_developers">Чат з розробниками</string> + <string name="tap_to_start_new_chat">Торкніться, щоб розпочати новий чат</string> + <string name="chat_with_developers">Чат із розробниками</string> <string name="you_have_no_chats">У вас немає чатів</string> - <string name="observer_cant_send_message_title">Ви не можете надсилати повідомлення!</string> - <string name="observer_cant_send_message_desc">Будь ласка, зверніться до адміністратора групи.</string> - <string name="file_will_be_received_when_contact_is_online">Файл буде отримано, коли ваш контакт буде онлайн, будь ласка, зачекайте або перевірте пізніше!</string> - <string name="icon_descr_video_snd_complete">Відео надіслано</string> - <string name="waiting_for_video">В очікуванні відео</string> + <string name="observer_cant_send_message_title">Ви не можете відправляти повідомлення!</string> + <string name="observer_cant_send_message_desc">Будь ласка, зв\'яжіться з адміністратором групи.</string> + <string name="file_will_be_received_when_contact_is_online">Файл буде отримано, коли ваш контакт буде в мережі, будь ласка, зачекайте або перевірте пізніше!</string> + <string name="icon_descr_video_snd_complete">Відео відправлене</string> + <string name="waiting_for_video">Очікування на відео</string> <string name="icon_descr_file">Файл</string> <string name="icon_descr_server_status_connected">Підключено</string> <string name="icon_descr_server_status_disconnected">Відключено</string> <string name="live_message">Живе повідомлення!</string> - <string name="ask_your_contact_to_enable_voice">Будь ласка, попросіть вашого контакту увімкнути відправку голосових повідомлень.</string> - <string name="send_live_message">Надіслати повідомлення в прямому ефірі</string> - <string name="send_live_message_desc">Надішліть повідомлення в реальному часі - воно буде оновлюватися для одержувача (одержувачів), поки ви його вводите</string> + <string name="ask_your_contact_to_enable_voice">Будь ласка, попросіть вашого контакту увімкнути надсилання голосових повідомлень.</string> + <string name="send_live_message">Надіслати живе повідомлення</string> + <string name="send_live_message_desc">Надішліть живе повідомлення - воно буде оновлюватися для одержувача(-ів), коли ви його набираєте</string> <string name="send_verb">Надіслати</string> - <string name="to_start_a_new_chat_help_header">Щоб почати новий чат</string> + <string name="to_start_a_new_chat_help_header">Щоб розпочати новий чат</string> <string name="chat_help_tap_button">Натисніть кнопку</string> - <string name="if_you_choose_to_reject_the_sender_will_not_be_notified">Якщо ви вирішите відхилити, відправник НЕ отримає сповіщення.</string> + <string name="if_you_choose_to_reject_the_sender_will_not_be_notified">Якщо ви виберете відхилити, відправник НЕ буде повідомлений.</string> <string name="clear_chat_button">Очистити чат</string> - <string name="invalid_contact_link">Невірне посилання!</string> - <string name="this_link_is_not_a_valid_connection_link">Це посилання не є дійсним посиланням для підключення!</string> - <string name="connection_request_sent">Запит на підключення відправлено!</string> - <string name="you_can_also_connect_by_clicking_the_link"><![CDATA[Ви також можете підключитися за посиланням. Якщо воно відкриється в браузері, натисніть кнопку <b>Відкрити в мобільному додатку</b>.]]></string> - <string name="create_one_time_link">Створіть одноразове посилання-запрошення</string> + <string name="invalid_contact_link">Неправильне посилання!</string> + <string name="this_link_is_not_a_valid_connection_link">Це посилання не є дійсним з\'єднувальним посиланням!</string> + <string name="connection_request_sent">Запит на з\'єднання відправлено!</string> + <string name="you_can_also_connect_by_clicking_the_link"><![CDATA[Ви також можете підключитися, клацнувши посилання. Якщо воно відкривається у браузері, клацніть кнопку <b>Відкрити у мобільному додатку</b>.]]></string> <string name="scan_code">Сканувати код</string> - <string name="scan_code_from_contacts_app">Відскануйте код безпеки з додатку вашого контакту.</string> - <string name="smp_servers_invalid_address">Неправильна адреса сервера!</string> - <string name="smp_servers_check_address">Перевірте адресу сервера та спробуйте ще раз.</string> + <string name="scan_code_from_contacts_app">Скануйте код безпеки з додатка вашого контакту.</string> + <string name="smp_servers_invalid_address">Невірна адреса сервера!</string> + <string name="smp_servers_check_address">Перевірте адресу сервера і спробуйте ще раз.</string> <string name="xftp_servers">Сервери XFTP</string> - <string name="install_simplex_chat_for_terminal">Встановіть SimpleX Chat для терміналу</string> - <string name="contribute">Зробити внесок</string> - <string name="rate_the_app">Оцініть програму</string> + <string name="install_simplex_chat_for_terminal">Встановити SimpleX Chat для терміналу</string> + <string name="contribute">Внести вклад</string> + <string name="rate_the_app">Оцініть додаток</string> <string name="your_SMP_servers">Ваші сервери SMP</string> <string name="your_XFTP_servers">Ваші сервери XFTP</string> <string name="using_simplex_chat_servers">Використання серверів SimpleX Chat.</string> - <string name="how_to">Як зробити</string> - <string name="callstatus_calling">телефоную…</string> - <string name="callstatus_missed">пропущений дзвінок</string> + <string name="how_to">Як користуватися</string> + <string name="callstatus_calling">дзвінок…</string> + <string name="callstatus_missed">пропущений виклик</string> <string name="callstatus_rejected">відхилений виклик</string> - <string name="incoming_video_call">Вхідний відеодзвінок</string> + <string name="incoming_video_call">Вхідний відеовиклик</string> <string name="incoming_audio_call">Вхідний аудіовиклик</string> - <string name="video_call_no_encryption">відеодзвінок (без шифрування e2e)</string> - <string name="call_on_lock_screen">Дзвінки на екрані блокування:</string> - <string name="call_connection_peer_to_peer">одноранговий</string> - <string name="icon_descr_hang_up">Покласти слухавку</string> - <string name="archive_created_on_ts">Створено на %1$s</string> - <string name="icon_descr_expand_role">Розширити вибір ролей</string> - <string name="chat_preferences_yes">Так</string> - <string name="contact_preferences">Налаштування контактів</string> + <string name="video_call_no_encryption">відеовиклик (не зашифрований e2e)</string> + <string name="call_on_lock_screen">Виклики на екрані блокування:</string> + <string name="call_connection_peer_to_peer">від абонента до абонента</string> + <string name="icon_descr_hang_up">Завершити дзвінок</string> + <string name="archive_created_on_ts">Створено %1$s</string> + <string name="icon_descr_expand_role">Розгорнути вибір ролі</string> + <string name="chat_preferences_yes">так</string> + <string name="contact_preferences">Налаштування контакту</string> <string name="v4_2_security_assessment_desc">Безпека SimpleX Chat була перевірена компанією Trail of Bits.</string> <string name="v4_3_irreversible_message_deletion_desc">Ваші контакти можуть дозволити повне видалення повідомлень.</string> <string name="database_will_be_encrypted">База даних буде зашифрована.</string> - <string name="keychain_error">Помилка ланцюжка ключів</string> + <string name="keychain_error">Помилка сховища ключів</string> <string name="unknown_error">Невідома помилка</string> - <string name="database_restore_error">Відновлення помилки бази даних</string> - <string name="snd_group_event_user_left">ви залишили</string> + <string name="database_restore_error">Помилка відновлення бази даних</string> + <string name="snd_group_event_user_left">ви залишили групу</string> <string name="group_member_status_accepted">підключення (прийнято)</string> <string name="button_add_members">Запросити учасників</string> <string name="button_leave_group">Покинути групу</string> - <string name="change_verb">Зміна</string> - <string name="sending_via">Відправлення через</string> + <string name="change_verb">Змінити</string> + <string name="sending_via">Надсилання через</string> <string name="network_status">Стан мережі</string> <string name="update_network_settings_question">Оновити налаштування мережі\?</string> - <string name="users_delete_data_only">Тільки локальні дані профілю</string> + <string name="users_delete_data_only">Локальні дані профілю тільки</string> <string name="incognito_random_profile">Ваш випадковий профіль</string> - <string name="feature_enabled">увімкнено</string> - <string name="feature_enabled_for_you">увімкнено для вас</string> - <string name="prohibit_direct_messages">Заборонити надсилати прямі повідомлення учасникам.</string> + <string name="feature_enabled">ввімкнено</string> + <string name="feature_enabled_for_you">ввімкнено для вас</string> + <string name="prohibit_direct_messages">Забороняйте надсилання прямих повідомлень учасникам.</string> <string name="delete_after">Видалити після</string> <string name="v4_2_security_assessment">Оцінка безпеки</string> - <string name="v4_2_group_links">Посилання на групи</string> - <string name="v4_3_improved_privacy_and_security">Покращена конфіденційність та безпека</string> + <string name="v4_2_group_links">Посилання на групу</string> + <string name="v4_3_improved_privacy_and_security">Покращена конфіденційність і безпека</string> <string name="v4_4_live_messages">Живі повідомлення</string> - <string name="v4_4_verify_connection_security">Перевірте безпеку підключення</string> - <string name="v4_4_verify_connection_security_desc">Порівняйте коди безпеки зі своїми контактами.</string> - <string name="v4_5_multiple_chat_profiles">Кілька профілів чату</string> - <string name="core_version">Основна версія: v%s</string> + <string name="v4_4_verify_connection_security">Перевірка безпеки підключення</string> + <string name="v4_4_verify_connection_security_desc">Порівнюйте коди безпеки із своїми контактами.</string> + <string name="v4_5_multiple_chat_profiles">Декілька профілів чату</string> + <string name="core_version">Версія ядра: v%s</string> <string name="delete_address__question">Видалити адресу\?</string> <string name="display_name__field">Ім\'я профілю:</string> - <string name="callstate_waiting_for_confirmation">чекаємо на підтвердження…</string> - <string name="privacy_redefined">Переосмислення конфіденційності</string> - <string name="people_can_connect_only_via_links_you_share">Люди можуть підключатися до вас лише за посиланнями, якими ви ділитеся.</string> + <string name="callstate_waiting_for_confirmation">очікування підтвердження…</string> + <string name="privacy_redefined">Приватність перевизначена</string> + <string name="people_can_connect_only_via_links_you_share">Люди можуть підключатися до вас лише за допомогою посилань, які ви надаєте.</string> <string name="how_simplex_works">Як працює SimpleX</string> - <string name="read_more_in_github">Детальніше читайте в нашому репозиторії GitHub.</string> - <string name="encrypted_audio_call">e2e зашифрований аудіодзвінок</string> - <string name="open_simplex_chat_to_accept_call">Відкрийте SimpleX Chat, щоб прийняти дзвінок</string> - <string name="status_e2e_encrypted">e2e зашифрований</string> + <string name="read_more_in_github">Докладніше читайте в нашому репозиторії на GitHub.</string> + <string name="encrypted_audio_call">зашифрований e2e аудіовиклик</string> + <string name="open_simplex_chat_to_accept_call">Відкрийте SimpleX Chat для прийняття виклику</string> + <string name="status_e2e_encrypted">e2e зашифровано</string> <string name="icon_descr_speaker_off">Динамік вимкнено</string> - <string name="icon_descr_call_pending_sent">Дзвінок в очікуванні</string> - <string name="icon_descr_call_missed">Пропущений дзвінок</string> - <string name="icon_descr_call_connecting">З\'єднувальний дзвінок</string> + <string name="icon_descr_call_pending_sent">Очікування виклику</string> + <string name="icon_descr_call_missed">Пропущений виклик</string> + <string name="icon_descr_call_connecting">Підключення виклику</string> <string name="privacy_and_security">Конфіденційність і безпека</string> <string name="your_privacy">Ваша конфіденційність</string> <string name="settings_section_title_settings">НАЛАШТУВАННЯ</string> <string name="settings_section_title_help">ДОПОМОГА</string> - <string name="settings_section_title_support">ПІДТРИМКА SIMPLEX CHAT</string> + <string name="settings_section_title_support">ПІДТРИМАЙТЕ SIMPLEX CHAT</string> <string name="stop_chat_to_export_import_or_delete_chat_database">Зупиніть чат, щоб експортувати, імпортувати або видалити базу даних чату. Ви не зможете отримувати та надсилати повідомлення, поки чат зупинено.</string> <string name="error_deleting_database">Помилка видалення бази даних чату</string> - <string name="notifications_will_be_hidden">Сповіщення будуть надходити лише до моменту зупинки програми!</string> - <string name="remove_passphrase">Видалити</string> + <string name="notifications_will_be_hidden">Сповіщення будуть доставлятися лише до зупинки додатка!</string> + <string name="remove_passphrase">Вилучити</string> <string name="encrypt_database">Зашифрувати</string> - <string name="update_database">Оновлення</string> - <string name="current_passphrase">Поточна парольна фраза…</string> - <string name="database_will_be_encrypted_and_passphrase_stored">База даних буде зашифрована, а пароль зберігатиметься у сховищі ключів.</string> - <string name="database_encryption_will_be_updated">Ключову фразу шифрування бази даних буде оновлено і збережено у сховищі ключів.</string> - <string name="rcv_group_event_member_added">запрошені %1$s</string> - <string name="rcv_group_event_invited_via_your_group_link">запрошені за посиланням у вашій групі</string> + <string name="update_database">Оновити</string> + <string name="current_passphrase">Поточна ключова фраза…</string> + <string name="database_will_be_encrypted_and_passphrase_stored">База даних буде зашифрована, і ключова фраза буде збережена в сховищі ключів.</string> + <string name="database_encryption_will_be_updated">Ключова фраза шифрування бази даних буде оновлена і збережена в сховищі ключів.</string> + <string name="rcv_group_event_member_added">запросив(ла) %1$s</string> + <string name="rcv_group_event_invited_via_your_group_link">запросив(ла) через ваше посилання на групу</string> <string name="snd_group_event_changed_member_role">ви змінили роль %s на %s</string> <string name="snd_conn_event_switch_queue_phase_completed_for_member">ви змінили адресу для %s</string> - <string name="snd_conn_event_switch_queue_phase_changing_for_member">зміна адреси для %s…</string> - <string name="invite_prohibited">Не вдається запросити контакт!</string> - <string name="group_info_section_title_num_members">%1$s УЧАСНИКИ</string> + <string name="snd_conn_event_switch_queue_phase_changing_for_member">змінює адресу для %s…</string> + <string name="invite_prohibited">Неможливо запросити контакт!</string> + <string name="group_info_section_title_num_members">%1$s УЧАСНИКІВ</string> <string name="button_delete_group">Видалити групу</string> <string name="group_link">Посилання на групу</string> - <string name="button_edit_group_profile">Редагування профілю групи</string> - <string name="create_group_link">Створити групове посилання</string> + <string name="button_edit_group_profile">Редагувати профіль групи</string> + <string name="create_group_link">Створити посилання на групу</string> <string name="change_member_role_question">Змінити роль у групі\?</string> - <string name="error_removing_member">Помилка видалення учасника</string> - <string name="group_main_profile_sent">Ваш профіль у чаті буде надіслано учасникам групи</string> + <string name="error_removing_member">Помилка при вилученні учасника</string> + <string name="group_main_profile_sent">Ваш профіль чату буде відправлений учасникам групи</string> <string name="save_color">Зберегти колір</string> - <string name="full_deletion">Видалити для всіх</string> + <string name="full_deletion">Видалення для всіх</string> <string name="voice_messages">Голосові повідомлення</string> - <string name="voice_prohibited_in_this_chat">Голосові повідомлення в цьому чаті заборонені.</string> - <string name="v4_3_voice_messages_desc">Максимум 40 секунд, отримується миттєво.</string> - <string name="v5_0_app_passcode_descr">Встановіть його замість системної автентифікації.</string> + <string name="voice_prohibited_in_this_chat">Голосові повідомлення заборонені в цьому чаті.</string> + <string name="v4_3_voice_messages_desc">Максимум 40 секунд, надходять миттєво.</string> + <string name="v5_0_app_passcode_descr">Встановіть його замість системної аутентифікації.</string> <string name="shutdown_alert_question">Вимкнути\?</string> - <string name="share_with_contacts">Поділіться з контактами</string> - <string name="your_profile_is_stored_on_device_and_shared_only_with_contacts_simplex_cannot_see_it">Ваш профіль зберігається на вашому пристрої та доступний лише вашим контактам. Сервери SimpleX не бачать ваш профіль.</string> - <string name="save_and_notify_contacts">Збереження та сповіщення контактів</string> - <string name="save_and_notify_group_members">Збереження та сповіщення учасників групи</string> - <string name="exit_without_saving">Вихід без збереження</string> - <string name="hide_profile">Приховати профіль</string> - <string name="password_to_show">Показати пароль</string> + <string name="share_with_contacts">Поділитися з контактами</string> + <string name="your_profile_is_stored_on_device_and_shared_only_with_contacts_simplex_cannot_see_it">Ваш профіль зберігається на вашому пристрої і обмінюється лише з ваших контактів. Сервери SimpleX не можуть його бачити.</string> + <string name="save_and_notify_contacts">Зберегти і повідомити контакти</string> + <string name="save_and_notify_group_members">Зберегти і повідомити учасників групи</string> + <string name="exit_without_saving">Вийти без збереження</string> + <string name="hide_profile">Сховати профіль</string> + <string name="password_to_show">Пароль для відображення</string> <string name="create_profile_button">Створити</string> - <string name="status_no_e2e_encryption">немає шифрування e2e</string> - <string name="status_contact_has_e2e_encryption">контакт має шифрування e2e</string> + <string name="status_no_e2e_encryption">без зашифрування e2e</string> + <string name="status_contact_has_e2e_encryption">контакт має зашифрування e2e</string> <string name="alert_text_msg_bad_hash">Хеш попереднього повідомлення відрізняється.</string> - <string name="confirm_passcode">Підтвердьте пароль</string> + <string name="confirm_passcode">Підтвердити пароль</string> <string name="new_passcode">Новий пароль</string> - <string name="settings_restart_app">Перезавантажити</string> + <string name="settings_restart_app">Перезапустити</string> <string name="your_chat_database">Ваша база даних чату</string> <string name="chat_is_stopped">Чат зупинено</string> <string name="chat_database_section">БАЗА ДАНИХ ЧАТУ</string> <string name="new_database_archive">Новий архів бази даних</string> <string name="stop_chat_question">Зупинити чат\?</string> - <string name="your_current_chat_database_will_be_deleted_and_replaced_with_the_imported_one">Вашу поточну базу даних чату буде ВИДАЛЕНО та ЗАМІНЕНО імпортованою. -\nЦю дію неможливо скасувати – ваш профіль, контакти, повідомлення та файли будуть безповоротно втрачені.</string> + <string name="your_current_chat_database_will_be_deleted_and_replaced_with_the_imported_one">Ваша поточна база даних чату буде ВИДАЛЕНА та ЗАМІНЕНА імпортованою. +\nЦя дія незворотня - ваш профіль, контакти, повідомлення та файли буде втрачено безповоротно.</string> <string name="chat_item_ttl_none">ніколи</string> <string name="chat_item_ttl_seconds">%s секунд(и)</string> - <string name="downgrade_and_open_chat">Пониження та відкритий чат</string> + <string name="downgrade_and_open_chat">Знизити версію та відкрити чат</string> <string name="new_member_role">Нова роль учасника</string> <string name="delete_link_question">Видалити посилання\?</string> <string name="delete_link">Видалити посилання</string> - <string name="switch_verb">Перемикач</string> - <string name="error_changing_role">Помилка, що змінює роль</string> + <string name="switch_verb">Перемкнути</string> + <string name="error_changing_role">Помилка при зміні ролі</string> <string name="group_display_name_field">Введіть назву групи:</string> <string name="group_full_name_field">Повна назва групи:</string> - <string name="error_saving_group_profile">Помилка збереження профілю групи</string> - <string name="network_options_reset_to_defaults">Скидання до налаштувань за замовчуванням</string> + <string name="error_saving_group_profile">Помилка при збереженні профілю групи</string> + <string name="network_options_reset_to_defaults">Скинути на замовчування</string> <string name="network_option_seconds_label">сек</string> <string name="network_option_protocol_timeout">Тайм-аут протоколу</string> <string name="network_options_save">Зберегти</string> - <string name="updating_settings_will_reconnect_client_to_all_servers">Оновлення налаштувань призведе до перепідключення клієнта до всіх серверів.</string> - <string name="user_mute">Вимкнути звук</string> - <string name="enter_password_to_show">Введіть пароль у пошуку</string> - <string name="both_you_and_your_contact_can_send_disappearing">Ви і ваш контакт можете надсилати зникаючі повідомлення.</string> - <string name="only_you_can_delete_messages">Тільки ви можете безповоротно видалити повідомлення (ваш контакт може позначити їх для видалення).</string> + <string name="updating_settings_will_reconnect_client_to_all_servers">Оновлення налаштувань призведе до повторного підключення клієнта до всіх серверів.</string> + <string name="user_mute">Приглушити</string> + <string name="enter_password_to_show">Введіть пароль для пошуку</string> + <string name="both_you_and_your_contact_can_send_disappearing">Як ви, так і ваш контакт можуть надсилати повідомлення, які зникають.</string> + <string name="only_you_can_delete_messages">Тільки ви можете невідворотно видаляти повідомлення (ваш контакт може позначати їх для видалення).</string> <string name="only_your_contact_can_add_message_reactions">Тільки ваш контакт може додавати реакції на повідомлення.</string> - <string name="only_your_contact_can_delete">Тільки ваш контакт може безповоротно видалити повідомлення (ви можете позначити їх для видалення).</string> + <string name="only_your_contact_can_delete">Тільки ваш контакт може невідворотно видаляти повідомлення (ви можете позначати їх для видалення).</string> <string name="only_your_contact_can_send_voice">Тільки ваш контакт може надсилати голосові повідомлення.</string> - <string name="prohibit_sending_disappearing">Заборонити надсилання зникаючих повідомлень.</string> - <string name="prohibit_message_deletion">Заборонити безповоротне видалення повідомлень.</string> + <string name="prohibit_sending_disappearing">Забороняйте надсилання повідомлень, які зникають.</string> + <string name="prohibit_message_deletion">Забороняйте невідворотне видалення повідомлень.</string> <string name="group_members_can_send_voice">Учасники групи можуть надсилати голосові повідомлення.</string> - <string name="ttl_m">%dм</string> + <string name="ttl_m">%dm</string> <string name="new_in_version">Нове в %s</string> - <string name="v5_1_self_destruct_passcode">Пароль самознищення</string> + <string name="v5_1_self_destruct_passcode">Самознищуючий пароль</string> <string name="v4_5_italian_interface">Італійський інтерфейс</string> - <string name="custom_time_unit_hours">годин</string> - <string name="custom_time_unit_days">днів</string> - <string name="custom_time_picker_select">Виберіть</string> - <string name="custom_time_picker_custom">нестандартний</string> - <string name="secret_text">таємниця</string> - <string name="join_group_button">Приєднуйтесь</string> + <string name="custom_time_unit_hours">години</string> + <string name="custom_time_unit_days">дні</string> + <string name="custom_time_picker_select">Вибрати</string> + <string name="custom_time_picker_custom">інше</string> + <string name="secret_text">прихований</string> + <string name="join_group_button">Приєднатися</string> <string name="role_in_group">Роль</string> - <string name="conn_level_desc_indirect">непрямі (%1$s)</string> - <string name="user_unmute">Увімкнути звук</string> - <string name="should_be_at_least_one_profile">Повинен бути принаймні один профіль користувача.</string> + <string name="conn_level_desc_indirect">непряме (%1$s)</string> + <string name="user_unmute">Відглушити</string> <string name="make_profile_private">Зробіть профіль приватним!</string> - <string name="feature_offered_item">запропонований %s</string> + <string name="feature_offered_item">запропоновано %s</string> <string name="v4_5_message_draft">Чернетка повідомлення</string> - <string name="v4_5_message_draft_descr">Зберегти чернетку останнього повідомлення з вкладеннями.</string> - <string name="disappearing_message">Повідомлення зникає</string> - <string name="send_disappearing_message">Надіслати зникаюче повідомлення</string> + <string name="v4_5_message_draft_descr">Зберігайте останню чернетку повідомлення із вкладеннями.</string> + <string name="disappearing_message">Зникне повідомлення</string> + <string name="send_disappearing_message">Надіслати зникне повідомлення</string> <string name="image_descr_profile_image">зображення профілю</string> <string name="icon_descr_more_button">Більше</string> <string name="create_profile">Створити профіль</string> - <string name="read_more_in_github_with_link"><![CDATA[Детальніше читайте в нашому репозиторії <font color="#0088ff">GitHub</font>.]]></string> - <string name="icon_descr_video_on">Відео включено</string> - <string name="alert_text_fragment_encryption_out_of_sync_old_database">Це може статися, коли ви або ваше підключення використовували стару резервну копію бази даних.</string> - <string name="restore_database">Відновлення резервної копії бази даних</string> + <string name="read_more_in_github_with_link"><![CDATA[Докладніше читайте в нашому репозиторії на <font color="#0088ff">GitHub</font>.]]></string> + <string name="icon_descr_video_on">Відео увімкнено</string> + <string name="alert_text_fragment_encryption_out_of_sync_old_database">Це може трапитися, якщо ви або ваше з\'єднання використовували застарілу резервну копію бази даних.</string> + <string name="restore_database">Відновити резервну копію бази даних</string> <string name="save_archive">Зберегти архів</string> <string name="group_invitation_item_description">запрошення до групи %1$s</string> - <string name="you_are_invited_to_group_join_to_connect_with_group_members">Вас запрошено до групи. Приєднуйтесь, щоб спілкуватися з учасниками групи.</string> + <string name="you_are_invited_to_group_join_to_connect_with_group_members">Вас запрошено в групу. Приєднуйтесь, щоб спілкуватися з учасниками групи.</string> <string name="message_reactions">Реакції на повідомлення</string> - <string name="accept_feature_set_1_day">Встановлюється 1 день</string> - <string name="prohibit_message_reactions">Заборонити реакцію на повідомлення.</string> - <string name="message_reactions_prohibited_in_this_chat">Реакції на повідомлення в цьому чаті заборонені.</string> + <string name="accept_feature_set_1_day">Встановити на 1 день</string> + <string name="prohibit_message_reactions">Забороняйте реакції на повідомлення.</string> + <string name="message_reactions_prohibited_in_this_chat">Реакції на повідомлення заборонені в цьому чаті.</string> <string name="ttl_s">%ds</string> <string name="custom_time_unit_minutes">хвилини</string> - <string name="v4_6_chinese_spanish_interface">Інтерфейс китайською та іспанською мовами</string> + <string name="v4_6_chinese_spanish_interface">Китайський та іспанський інтерфейс</string> <string name="connection_local_display_name">підключення %1$d</string> <string name="error_loading_smp_servers">Помилка завантаження серверів SMP</string> - <string name="failed_to_create_user_duplicate_title">Дублююче ім\'я користувача!</string> - <string name="error_sending_message">Помилка надсилання повідомлення</string> + <string name="failed_to_create_user_duplicate_title">Дубль імені відображення!</string> + <string name="error_sending_message">Помилка відправлення повідомлення</string> <string name="sender_cancelled_file_transfer">Відправник скасував передачу файлу.</string> <string name="error_receiving_file">Помилка отримання файлу</string> <string name="error_creating_address">Помилка створення адреси</string> - <string name="invalid_connection_link">Неправильне посилання для підключення</string> - <string name="error_accepting_contact_request">Помилка при прийнятті запиту на контакт</string> + <string name="invalid_connection_link">Неправильне посилання на підключення</string> + <string name="error_accepting_contact_request">Помилка прийняття запиту на контакт</string> <string name="smp_server_test_create_file">Створити файл</string> - <string name="error_deleting_user">Помилка видалення профілю користувача</string> + <string name="error_deleting_user">Помилка видалення користувача</string> <string name="error_updating_user_privacy">Помилка оновлення конфіденційності користувача</string> - <string name="to_preserve_privacy_simplex_has_background_service_instead_of_push_notifications_it_uses_a_few_pc_battery"><![CDATA[Щоб зберегти вашу конфіденційність, замість push-сповіщень програма має <b>SimpleX фонову службу</b> – вона використовує кілька відсотків заряду акумулятора на день.]]></string> + <string name="to_preserve_privacy_simplex_has_background_service_instead_of_push_notifications_it_uses_a_few_pc_battery"><![CDATA[Для збереження вашої конфіденційності, замість торкання сповіщень, програма використовує <b>фоновий сервіс SimpleX</b> – він використовує кілька відсотків батареї щодня.]]></string> <string name="periodic_notifications">Періодичні сповіщення</string> - <string name="simplex_service_notification_title">Сервіс SimpleX Chat</string> + <string name="simplex_service_notification_title">Служба чату SimpleX</string> <string name="notifications_mode_periodic_desc">Перевіряє нові повідомлення кожні 10 хвилин протягом 1 хвилини</string> <string name="notification_preview_mode_hidden">Приховано</string> - <string name="notification_preview_mode_message_desc">Показати контакт та повідомлення</string> - <string name="notification_display_mode_hidden_desc">Приховати контакт і повідомлення</string> - <string name="la_notice_title_simplex_lock">SimpleX Lock</string> - <string name="la_notice_to_protect_your_information_turn_on_simplex_lock_you_will_be_prompted_to_complete_authentication_before_this_feature_is_enabled">Щоб захистити вашу інформацію, увімкніть SimpleX Lock. -\nПеред увімкненням цієї функції вам буде запропоновано пройти автентифікацію.</string> - <string name="auth_log_in_using_credential">Увійдіть, використовуючи свій обліковий запис</string> - <string name="auth_enable_simplex_lock">Увімкнути SimpleX Lock</string> - <string name="lock_not_enabled">SimpleX Lock не ввімкнено!</string> - <string name="share_verb">Поділіться</string> + <string name="notification_preview_mode_message_desc">Показати контакт і повідомлення</string> + <string name="notification_display_mode_hidden_desc">Сховати контакт і повідомлення</string> + <string name="la_notice_title_simplex_lock">Блокування SimpleX</string> + <string name="la_notice_to_protect_your_information_turn_on_simplex_lock_you_will_be_prompted_to_complete_authentication_before_this_feature_is_enabled">Щоб захистити вашу інформацію, увімкніть блокування SimpleX. +\nВам буде запропоновано завершити аутентифікацію перед увімкненням цієї функції.</string> + <string name="auth_log_in_using_credential">Увійти за допомогою своїх облікових даних</string> + <string name="auth_enable_simplex_lock">Увімкнути блокування SimpleX</string> + <string name="lock_not_enabled">Блокування SimpleX не увімкнено!</string> + <string name="share_verb">Поділитися</string> <string name="copy_verb">Копіювати</string> <string name="moderate_message_will_be_deleted_warning">Повідомлення буде видалено для всіх учасників.</string> - <string name="stop_snd_file__message">Надсилання файлу буде зупинено.</string> + <string name="stop_snd_file__message">Відправлення файлу буде зупинено.</string> <string name="stop_rcv_file__title">Зупинити отримання файлу\?</string> <string name="stop_rcv_file__message">Отримання файлу буде зупинено.</string> <string name="stop_file__confirm">Зупинити</string> @@ -580,299 +577,298 @@ <string name="revoke_file__message">Файл буде видалено з серверів.</string> <string name="revoke_file__confirm">Відкликати</string> <string name="icon_descr_sent_msg_status_unauthorized_send">несанкціонована відправка</string> - <string name="personal_welcome">Ласкаво просимо %1$s!</string> + <string name="personal_welcome">Ласкаво просимо, %1$s!</string> <string name="welcome">Ласкаво просимо!</string> <string name="this_text_is_available_in_settings">Цей текст доступний у налаштуваннях</string> - <string name="group_preview_you_are_invited">вас запрошують до групи</string> + <string name="group_preview_you_are_invited">вас запрошено в групу</string> <string name="share_message">Поділитися повідомленням…</string> - <string name="share_image">Поділитися медіафайлами…</string> - <string name="share_file">Поділіться файлом…</string> - <string name="images_limit_desc">Одночасно можна надіслати лише 10 зображень</string> - <string name="videos_limit_desc">Одночасно можна надіслати лише 10 відео</string> - <string name="image_decoding_exception_title">Помилка декодування</string> - <string name="image_decoding_exception_desc">Зображення не може бути декодовано. Будь ласка, спробуйте інше зображення або зверніться до розробників.</string> + <string name="share_image">Поділитися медіа…</string> + <string name="share_file">Поділитися файлом…</string> + <string name="images_limit_desc">Одночасно можна відправити лише 10 зображень</string> + <string name="videos_limit_desc">Одночасно можна відправити лише 10 відео</string> + <string name="image_decoding_exception_title">Помилка декодування зображення</string> + <string name="image_decoding_exception_desc">Неможливо декодувати зображення. Спробуйте інше зображення або зв\'яжіться з розробниками.</string> <string name="image_descr">Зображення</string> - <string name="image_will_be_received_when_contact_completes_uploading">Зображення буде отримано, коли ваш контакт завершить завантаження.</string> - <string name="image_will_be_received_when_contact_is_online">Зображення буде отримано, коли ваш контакт буде онлайн, будь ласка, зачекайте або перевірте пізніше!</string> - <string name="image_saved">Зображення збережено до Галереї</string> + <string name="image_will_be_received_when_contact_completes_uploading">Зображення буде отримано, коли ваш контакт завершить його вивантаження.</string> + <string name="image_will_be_received_when_contact_is_online">Зображення буде отримано, коли ваш контакт буде в мережі, будь ласка, зачекайте або перевірте пізніше!</string> + <string name="image_saved">Зображення збережено в галереї</string> <string name="video_descr">Відео</string> - <string name="contact_sent_large_file">Ваш контакт надіслав файл, розмір якого перевищує дозволений максимальний розмір (%1$s).</string> - <string name="maximum_supported_file_size">Наразі максимальний підтримуваний розмір файлу: %1$s .</string> - <string name="switch_receiving_address_desc">Ця функція є експериментальною! Вона працюватиме, тільки якщо на іншому клієнті встановлено версію 4.2. Після завершення зміни адреси ви побачите повідомлення в бесіді - будь ласка, перевірте, чи можете ви отримувати повідомлення від цього контакту (або члена групи).</string> - <string name="verify_security_code">Підтвердіть код безпеки</string> - <string name="icon_descr_send_message">Відправити повідомлення</string> + <string name="contact_sent_large_file">Ваш контакт відправив файл, розмір якого більший, ніж поточно підтримуваний максимальний розмір (%1$s).</string> + <string name="maximum_supported_file_size">Поточно максимально підтримуваний розмір файлу - %1$s.</string> + <string name="switch_receiving_address_desc">Адреса для отримання буде змінена на інший сервер. Зміна адреси завершиться після включення відправника.</string> + <string name="verify_security_code">Перевірити код безпеки</string> + <string name="icon_descr_send_message">Надіслати повідомлення</string> <string name="icon_descr_record_voice_message">Записати голосове повідомлення</string> - <string name="only_stored_on_members_devices">(зберігається тільки учасниками групи)</string> - <string name="toast_permission_denied">У дозволі відмовлено!</string> + <string name="only_stored_on_members_devices">(зберігається лише на пристроях учасників групи)</string> + <string name="toast_permission_denied">Доступ відхилено!</string> <string name="use_camera_button">Камера</string> - <string name="thank_you_for_installing_simplex">Дякуємо, що встановили SimpleX Chat!</string> - <string name="scan_QR_code_to_connect_to_contact_who_shows_QR_code"><![CDATA[<b>Відскануйте QR-код</b>: щоб з\'єднатися з вашим контактом, який покаже вам QR-код.]]></string> - <string name="if_you_received_simplex_invitation_link_you_can_open_in_browser">Якщо ви отримали посилання на запрошення SimpleX Chat, ви можете відкрити його у своєму браузері:</string> - <string name="clear_chat_menu_action">Чисто</string> + <string name="thank_you_for_installing_simplex">Дякуємо за установку SimpleX Chat!</string> + <string name="if_you_received_simplex_invitation_link_you_can_open_in_browser">Якщо ви отримали запрошення від SimpleX Chat, ви можете відкрити його у вашому браузері:</string> + <string name="clear_chat_menu_action">Очистити</string> <string name="delete_contact_menu_action">Видалити</string> <string name="delete_group_menu_action">Видалити</string> - <string name="mark_read">Позначити прочитано</string> - <string name="mark_unread">Позначити як непрочитане</string> + <string name="mark_read">Позначити прочитаним</string> + <string name="mark_unread">Позначити непрочитаним</string> <string name="set_contact_name">Встановити ім\'я контакту</string> - <string name="you_accepted_connection">Ви прийняли підключення</string> - <string name="delete_pending_connection__question">Видалити очікуване з\'єднання\?</string> - <string name="alert_text_connection_pending_they_need_to_be_online_can_delete_and_retry">Ваш контакт має бути онлайн, щоб з’єднання завершилося. -\nВи можете скасувати це з’єднання та видалити контакт (і спробувати пізніше з новим посиланням).</string> - <string name="image_descr_simplex_logo">SimpleX Логотип</string> + <string name="you_accepted_connection">Ви прийняли з\'єднання</string> + <string name="delete_pending_connection__question">Видалити очікуюче з\'єднання?</string> + <string name="alert_text_connection_pending_they_need_to_be_online_can_delete_and_retry">Ваш контакт повинен бути в мережі, щоб завершити з\'єднання. +\nВи можете скасувати це з\'єднання і видалити контакт (і спробувати пізніше за допомогою нового посилання).</string> + <string name="image_descr_simplex_logo">Логотип SimpleX</string> <string name="icon_descr_email">Електронна пошта</string> <string name="this_QR_code_is_not_a_link">Цей QR-код не є посиланням!</string> - <string name="you_will_be_connected_when_group_host_device_is_online">Вас буде підключено до групи, коли пристрій хоста групи буде онлайн, зачекайте або перевірте пізніше!</string> - <string name="you_will_be_connected_when_your_connection_request_is_accepted">Ви будете підключені, коли ваш запит на підключення буде прийнято, будь ласка, зачекайте або перевірте пізніше!</string> - <string name="share_invitation_link">Поділіться одноразовим посиланням</string> - <string name="learn_more">Детальніше</string> - <string name="scan_qr_to_connect_to_contact">Щоб підключитися, ваш контакт може відсканувати QR-код або скористатися посиланням у додатку.</string> - <string name="if_you_cant_meet_in_person">Якщо ви не можете зустрітися особисто, покажіть QR-код у відеодзвінку або поділіться посиланням.</string> - <string name="you_can_share_your_address">Ви можете поділитися своєю адресою у вигляді посилання або QR-коду - будь-хто зможе зв\'язатися з вами.</string> + <string name="you_will_be_connected_when_group_host_device_is_online">Ви будете підключені до групи, коли пристрій господаря групи буде в мережі, зачекайте або перевірте пізніше!</string> + <string name="you_will_be_connected_when_your_connection_request_is_accepted">Вас підключать, коли ваш запит на з\'єднання буде прийнятий, зачекайте або перевірте пізніше!</string> + <string name="share_invitation_link">Поділитися 1-разовим посиланням</string> + <string name="learn_more">Дізнатися більше</string> + <string name="scan_qr_to_connect_to_contact">Щоб підключитися, ваш контакт може сканувати QR-код або використовувати посилання у додатку.</string> + <string name="if_you_cant_meet_in_person">Якщо ви не можете зустрітися особисто, покажіть QR-код у відеовиклику або поділіться посиланням.</string> + <string name="you_can_share_your_address">Ви можете поділитися своєю адресою в якості посилання або QR-коду - кожен може підключитися до вас.</string> <string name="paste_button">Вставити</string> - <string name="this_string_is_not_a_connection_link">Цей рядок не є посиланням для з\'єднання!</string> + <string name="this_string_is_not_a_connection_link">Цей рядок не є з\'єднувальним посиланням!</string> <string name="security_code">Код безпеки</string> - <string name="mark_code_verified">Позначку перевірено</string> + <string name="mark_code_verified">Позначити, що перевірено</string> <string name="your_chat_profiles">Ваші профілі чату</string> - <string name="database_passphrase_and_export">Ключова фраза бази даних та експорт</string> - <string name="markdown_in_messages">Націнка в повідомленнях</string> - <string name="chat_with_the_founder">Надсилайте запитання та ідеї</string> - <string name="smp_servers_enter_manually">Увійдіть на сервер вручну</string> + <string name="database_passphrase_and_export">Пароль бази даних та експорт</string> + <string name="markdown_in_messages">Markdown у повідомленнях</string> + <string name="chat_with_the_founder">Надсилайте питання та ідеї</string> + <string name="smp_servers_enter_manually">Ввести адресу сервера вручну</string> <string name="smp_servers_preset_server">Попередньо встановлений сервер</string> - <string name="smp_servers_your_server_address">Ваша адреса сервера</string> + <string name="smp_servers_your_server_address">Адреса вашого сервера</string> <string name="smp_servers_per_user">Сервери для нових підключень вашого поточного профілю чату</string> - <string name="use_simplex_chat_servers__question">Використовуєте сервери SimpleX Chat\?</string> - <string name="enter_one_ICE_server_per_line">Сервери ICE (по одному на лінію)</string> + <string name="use_simplex_chat_servers__question">Використовувати сервери SimpleX Chat?</string> + <string name="enter_one_ICE_server_per_line">Сервери ICE (один на рядок)</string> <string name="error_saving_ICE_servers">Помилка збереження серверів ICE</string> - <string name="network_use_onion_hosts_required_desc">Onion hosts will be required for connection. -\nPlease note: you will not be able to connect to the servers without .onion address.</string> - <string name="network_use_onion_hosts_prefer_desc_in_alert">Onion хости будуть використовуватися за наявності.</string> - <string name="network_use_onion_hosts_required_desc_in_alert">Для з\'єднання будуть потрібні хости onion.</string> - <string name="show_developer_options">Показати опції розробника</string> + <string name="network_use_onion_hosts_required_desc">.Onion-хости будуть обов\'язковими для підключення. +\nЗверніть увагу: ви не зможете підключитися до серверів без адреси .onion.</string> + <string name="network_use_onion_hosts_prefer_desc_in_alert">Хости .onion будуть використовуватися, якщо доступні.</string> + <string name="network_use_onion_hosts_required_desc_in_alert">Хости .onion будуть обов\'язковими для підключення.</string> + <string name="show_developer_options">Показати параметри розробника</string> <string name="developer_options">Ідентифікатори бази даних та опція ізоляції транспорту.</string> <string name="shutdown_alert_desc">Сповіщення перестануть працювати, поки ви не перезапустите додаток</string> <string name="you_can_create_it_later">Ви можете створити його пізніше</string> <string name="your_current_profile">Ваш поточний профіль</string> <string name="delete_image">Видалити зображення</string> <string name="save_preferences_question">Зберегти налаштування\?</string> - <string name="save_and_notify_contact">Зберегти та повідомити контакт</string> + <string name="save_and_notify_contact">Зберегти і повідомити контакт</string> <string name="save_profile_password">Зберегти пароль профілю</string> - <string name="hidden_profile_password">Прихований пароль профілю</string> - <string name="profile_is_only_shared_with_your_contacts">Профіль доступний лише вашим контактам.</string> - <string name="display_name_cannot_contain_whitespace">Ім\'я не може містити пробілів.</string> - <string name="how_to_use_markdown">Як використовувати націнку</string> - <string name="you_can_use_markdown_to_format_messages__prompt">Ви можете використовувати розмітку для форматування повідомлень:</string> + <string name="hidden_profile_password">Пароль схованого профілю</string> + <string name="profile_is_only_shared_with_your_contacts">Профіль обмінюється лише з вашими контактами.</string> + <string name="display_name_cannot_contain_whitespace">Ім\'я для відображення не може містити пробіли.</string> + <string name="how_to_use_markdown">Як використовувати markdown</string> + <string name="you_can_use_markdown_to_format_messages__prompt">Ви можете використовувати markdown для форматування повідомлень:</string> <string name="create_your_profile">Створіть свій профіль</string> - <string name="make_private_connection">Створіть приватне з\'єднання</string> - <string name="many_people_asked_how_can_it_deliver"><![CDATA[Багато людей запитували: <i>якщо SimpleX не має ідентифікаторів користувачів, як він може доставляти повідомлення\?</i>]]></string> - <string name="you_control_servers_to_receive_your_contacts_to_send"><![CDATA[Ви контролюєте, через який(і) сервер(и) <b>отримувати</b> повідомлення, ваші контакти - сервери, які ви використовуєте для надсилання їм повідомлень.]]></string> - <string name="only_client_devices_store_contacts_groups_e2e_encrypted_messages"><![CDATA[Лише клієнтські пристрої зберігають профілі користувачів, контакти, групи та повідомлення, надіслані за допомогою <b>дворівневого наскрізного шифрування</b>.]]></string> + <string name="make_private_connection">Створіть приватне підключення</string> + <string name="many_people_asked_how_can_it_deliver"><![CDATA[Багато людей питають: <i>як в SimpleX можливо доставляти повідомлення, якщо він не має ідентифікаторів користувачів?</i>]]></string> + <string name="you_control_servers_to_receive_your_contacts_to_send"><![CDATA[Ви контролюєте, через які сервери <b>отримувати</b> повідомлення, ваші контакти – сервери, які ви використовуєте для надсилання повідомлень їм.]]></string> + <string name="only_client_devices_store_contacts_groups_e2e_encrypted_messages"><![CDATA[Тільки пристрої клієнта зберігають профілі користувачів, контакти, групи та повідомлення, відправлені за допомогою <b>шифрування на двох рівнях</b>.]]></string> <string name="onboarding_notifications_mode_title">Приватні сповіщення</string> - <string name="onboarding_notifications_mode_service_desc"><![CDATA[<b>Використовує більше заряду акумулятора</b>! Завжди працює фоновий сервіс - сповіщення показуються, як тільки з\'являються повідомлення.]]></string> + <string name="onboarding_notifications_mode_service_desc"><![CDATA[<b>Споживає більше заряду акумулятора</b>! Фоновий сервіс завжди працює – сповіщення відображаються, як тільки повідомлення доступні.]]></string> <string name="paste_the_link_you_received">Вставте отримане посилання</string> <string name="icon_descr_video_off">Відео вимкнено</string> - <string name="icon_descr_call_ended">Дзвінок завершено</string> - <string name="alert_text_msg_bad_id">Ідентифікатор наступного повідомлення неправильний (менше або дорівнює попередньому). -\nЦе може статися через помилку або коли з\'єднання скомпрометовано.</string> - <string name="self_destruct_passcode_enabled">Пароль самознищення ввімкнено!</string> + <string name="icon_descr_call_ended">Завершено виклик</string> + <string name="alert_text_msg_bad_id">Ідентифікатор наступного повідомлення є неправильним (менший або рівний попередньому). +\nЦе може трапитися через якусь помилку або коли з\'єднання скомпрометоване.</string> + <string name="self_destruct_passcode_enabled">Пароль самознищення увімкнено!</string> <string name="self_destruct_passcode_changed">Пароль самознищення змінено!</string> <string name="your_profile_is_stored_on_your_device">Ваш профіль, контакти та доставлені повідомлення зберігаються на вашому пристрої.</string> <string name="settings_section_title_you">ВИ</string> <string name="settings_section_title_device">ПРИСТРІЙ</string> - <string name="settings_shutdown">Вимкнення</string> + <string name="settings_shutdown">Вимкнути</string> <string name="settings_section_title_themes">ТЕМИ</string> <string name="settings_section_title_messages">ПОВІДОМЛЕННЯ ТА ФАЙЛИ</string> - <string name="chat_is_running">Чат запущено</string> - <string name="import_database">Імпорт бази даних</string> + <string name="chat_is_running">Чат працює</string> + <string name="import_database">Імпортувати базу даних</string> <string name="old_database_archive">Старий архів бази даних</string> <string name="delete_database">Видалити базу даних</string> - <string name="set_password_to_export">Встановіть парольну фразу для експорту</string> - <string name="set_password_to_export_desc">База даних зашифрована за допомогою випадкової парольної фрази. Будь ласка, змініть його перед експортом.</string> + <string name="set_password_to_export">Встановити пароль для експорту</string> + <string name="set_password_to_export_desc">База даних зашифрована випадковим паролем. Змініть його перед експортом.</string> <string name="error_exporting_chat_database">Помилка експорту бази даних чату</string> <string name="import_database_question">Імпортувати базу даних чату\?</string> <string name="error_importing_database">Помилка імпорту бази даних чату</string> <string name="delete_chat_profile_question">Видалити профіль чату\?</string> - <string name="delete_files_and_media_desc">Цю дію неможливо скасувати - всі отримані та надіслані файли і медіа будуть видалені. Зображення з низькою роздільною здатністю залишаться.</string> - <string name="delete_messages">Видалення повідомлень</string> - <string name="update_database_passphrase">Оновити парольну фразу бази даних</string> - <string name="encrypted_with_random_passphrase">База даних зашифрована за допомогою випадкової парольної фрази, яку ви можете змінити.</string> - <string name="database_passphrase_will_be_updated">Парольну фразу шифрування бази даних буде оновлено.</string> - <string name="store_passphrase_securely">Будь ласка, зберігайте пароль надійно, ви НЕ зможете змінити його, якщо втратите.</string> - <string name="wrong_passphrase">Неправильна парольна фраза бази даних</string> - <string name="passphrase_is_different">Пароль до бази даних відрізняється від збереженого у сховищі ключів.</string> - <string name="database_backup_can_be_restored">Спроба змінити пароль бази даних не була завершена.</string> + <string name="delete_files_and_media_desc">Цю дію неможливо відмінити - всі отримані та надіслані файли та медіа будуть видалені. Зображення низької роздільної здатності залишаться.</string> + <string name="delete_messages">Видалити повідомлення</string> + <string name="update_database_passphrase">Оновити ключову фразу бази даних</string> + <string name="encrypted_with_random_passphrase">База даних зашифрована випадковою ключовою фразою, яку можна змінити.</string> + <string name="database_passphrase_will_be_updated">Ключова фраза шифрування бази даних буде оновлена.</string> + <string name="store_passphrase_securely">Будь ласка, зберігайте ключову фразу надійно, ви НЕ зможете її змінити, якщо втратите її.</string> + <string name="wrong_passphrase">Неправильна ключова фраза бази даних</string> + <string name="passphrase_is_different">Ключова фраза бази даних відрізняється від збереженої в сховищі ключів.</string> + <string name="database_backup_can_be_restored">Спроба змінити ключову фразу бази даних не була завершена.</string> <string name="restore_database_alert_title">Відновити резервну копію бази даних\?</string> - <string name="restore_database_alert_desc">Будь ласка, введіть попередній пароль після відновлення резервної копії бази даних. Ця дія не може бути скасована.</string> - <string name="join_group_incognito_button">Приєднуйтесь інкогніто</string> - <string name="rcv_group_event_member_left">ліворуч</string> - <string name="rcv_group_event_changed_member_role">змінили роль %s на %s</string> - <string name="rcv_group_event_group_deleted">видалена група</string> + <string name="restore_database_alert_desc">Будь ласка, введіть попередній пароль після відновлення резервної копії бази даних. Цю дію неможливо скасувати.</string> + <string name="join_group_incognito_button">Приєднатися анонімно</string> + <string name="rcv_group_event_member_left">вийшов(ла)</string> + <string name="rcv_group_event_changed_member_role">змінив(ла) роль %s на %s</string> + <string name="rcv_group_event_group_deleted">групу видалено</string> <string name="snd_group_event_group_profile_updated">оновлено профіль групи</string> - <string name="rcv_conn_event_switch_queue_phase_completed">змінили для вас адресу</string> + <string name="rcv_conn_event_switch_queue_phase_completed">змінив(ла) адресу для вас</string> <string name="rcv_conn_event_switch_queue_phase_changing">змінює адресу…</string> <string name="group_member_role_member">учасник</string> - <string name="group_member_status_left">ліворуч</string> + <string name="group_member_status_left">залишено</string> <string name="group_member_status_group_deleted">групу видалено</string> - <string name="group_member_status_invited">запрошені</string> + <string name="group_member_status_invited">запрошено</string> <string name="group_member_status_introduced">підключення (введено)</string> <string name="invite_to_group_button">Запросити до групи</string> <string name="skip_inviting_button">Пропустити запрошення учасників</string> - <string name="num_contacts_selected">%d вибрано контакт(и)</string> + <string name="num_contacts_selected">%d вибрано контактів</string> <string name="group_info_member_you">ви: %1$s</string> - <string name="delete_group_for_all_members_cannot_undo_warning">Група буде видалена для всіх учасників - це неможливо скасувати!</string> - <string name="delete_group_for_self_cannot_undo_warning">Група буде видалена для вас - це не може бути скасовано!</string> + <string name="delete_group_for_all_members_cannot_undo_warning">Група буде видалена для всіх учасників - цю дію неможливо скасувати!</string> + <string name="delete_group_for_self_cannot_undo_warning">Група буде видалена для вас - цю дію неможливо скасувати!</string> <string name="button_create_group_link">Створити посилання</string> - <string name="error_updating_link_for_group">Помилка оновлення посилання на групу</string> - <string name="error_deleting_link_for_group">Помилка видалення посилання на групу</string> - <string name="only_group_owners_can_change_prefs">Тільки власники груп можуть змінювати налаштування групи.</string> - <string name="info_row_updated_at">Запис оновлено за</string> - <string name="info_row_sent_at">Надіслано на</string> - <string name="info_row_moderated_at">Модерується на</string> - <string name="info_row_disappears_at">Зникає за</string> + <string name="error_updating_link_for_group">Помилка при оновленні посилання на групу</string> + <string name="error_deleting_link_for_group">Помилка при видаленні посилання на групу</string> + <string name="only_group_owners_can_change_prefs">Змінювати налаштування групи можуть лише її власники.</string> + <string name="info_row_updated_at">Запис оновлено</string> + <string name="info_row_sent_at">Надіслано</string> + <string name="info_row_moderated_at">Модеровано о</string> + <string name="info_row_disappears_at">Зникає о</string> <string name="share_text_database_id">Ідентифікатор бази даних: %d</string> - <string name="share_text_updated_at">Запис оновлено за: %s</string> - <string name="share_text_moderated_at">Модерується на: %s</string> - <string name="share_text_disappears_at">Зникає в: %s</string> - <string name="item_info_current">(поточний)</string> - <string name="button_remove_member">Видалити учасника</string> - <string name="member_role_will_be_changed_with_notification">Роль буде змінено на \"%s\". Всі учасники групи будуть повідомлені про це.</string> + <string name="share_text_updated_at">Запис оновлено о: %s</string> + <string name="share_text_moderated_at">Модеровано о: %s</string> + <string name="share_text_disappears_at">Зникає о: %s</string> + <string name="item_info_current">(поточне)</string> + <string name="button_remove_member">Вилучити учасника</string> + <string name="member_role_will_be_changed_with_notification">Роль буде змінено на \"%s\". Всі учасники групи будуть сповіщені.</string> <string name="member_role_will_be_changed_with_invitation">Роль буде змінено на \"%s\". Учасник отримає нове запрошення.</string> <string name="info_row_group">Група</string> - <string name="group_welcome_title">Вітальне повідомлення</string> + <string name="group_welcome_title">Ласкаво просимо</string> <string name="group_profile_is_stored_on_members_devices">Профіль групи зберігається на пристроях учасників, а не на серверах.</string> <string name="save_group_profile">Зберегти профіль групи</string> - <string name="users_delete_with_connections">Підключення профілю та сервера</string> + <string name="users_delete_with_connections">Профіль і підключення до серверів</string> <string name="user_unhide">Показати</string> - <string name="you_can_hide_or_mute_user_profile">Ви можете приховати або вимкнути звук профілю користувача - утримуйте його для виклику меню.</string> + <string name="you_can_hide_or_mute_user_profile">Ви можете приховати або вимкнути звук профілю користувача - утримуйте його для меню.</string> <string name="unhide_profile">Показати профіль</string> <string name="unhide_chat_profile">Показати профіль чату</string> - <string name="incognito_info_share">Коли ви ділитеся з кимось своїм профілем інкогніто, цей профіль буде використовуватися для груп, до яких вони вас запрошують.</string> - <string name="theme_light">Світлий</string> + <string name="incognito_info_share">Коли ви ділитесь анонімним профілем з кимось, цей профіль буде використовуватися для груп, до яких вас запрошують.</string> + <string name="theme_light">Світла</string> <string name="import_theme_error">Помилка імпорту теми</string> <string name="group_preferences">Налаштування групи</string> - <string name="timed_messages">Зникнення повідомлень</string> - <string name="feature_enabled_for_contact">увімкнено для контакту</string> + <string name="timed_messages">Повідомлення зникнення</string> + <string name="feature_enabled_for_contact">ввімкнено для контакту</string> <string name="feature_off">вимкнено</string> <string name="feature_received_prohibited">отримано, заборонено</string> - <string name="contacts_can_mark_messages_for_deletion">Контакти можуть позначати повідомлення для видалення; ви зможете їх переглянути.</string> - <string name="prohibit_calls">Заборонити аудіо/відеодзвінки.</string> - <string name="only_you_can_send_disappearing">Тільки ви можете надсилати зникаючі повідомлення.</string> - <string name="disappearing_prohibited_in_this_chat">Зникаючі повідомлення в цьому чаті заборонені.</string> - <string name="message_deletion_prohibited">У цьому чаті заборонено безповоротне видалення повідомлень.</string> - <string name="both_you_and_your_contact_can_send_voice">Надсилати голосові повідомлення можете як ви, так і ваш контакт.</string> + <string name="contacts_can_mark_messages_for_deletion">Контакти можуть позначати повідомлення для видалення; ви зможете їх переглядати.</string> + <string name="prohibit_calls">Забороняйте аудіо/відео дзвінки.</string> + <string name="only_you_can_send_disappearing">Тільки ви можете надсилати повідомлення, які зникають.</string> + <string name="disappearing_prohibited_in_this_chat">Зникнення повідомлень заборонене в цьому чаті.</string> + <string name="message_deletion_prohibited">Невідворотне видалення повідомлень заборонено в цьому чаті.</string> + <string name="both_you_and_your_contact_can_send_voice">Як ви, так і ваш контакт можуть надсилати голосові повідомлення.</string> <string name="only_you_can_send_voice">Тільки ви можете надсилати голосові повідомлення.</string> <string name="only_you_can_add_message_reactions">Тільки ви можете додавати реакції на повідомлення.</string> <string name="prohibit_message_reactions_group">Заборонити реакції на повідомлення.</string> - <string name="disappearing_messages_are_prohibited">У цій групі заборонено зникаючі повідомлення.</string> - <string name="group_members_can_send_dms">Учасники групи можуть надсилати прямі повідомлення.</string> - <string name="direct_messages_are_prohibited_in_chat">У цій групі заборонені прямі повідомлення між учасниками.</string> - <string name="group_members_can_delete">Учасники групи можуть безповоротно видаляти надіслані повідомлення.</string> - <string name="message_deletion_prohibited_in_chat">У цій групі заборонено безповоротне видалення повідомлень.</string> - <string name="voice_messages_are_prohibited">Голосові повідомлення в цій групі заборонені.</string> + <string name="disappearing_messages_are_prohibited">Самознищувальні повідомлення заборонені в цій групі.</string> + <string name="group_members_can_send_dms">Учасники групи можуть надсилати приватні повідомлення.</string> + <string name="direct_messages_are_prohibited_in_chat">Приватні повідомлення між учасниками заборонені в цій групі.</string> + <string name="group_members_can_delete">Учасники групи можуть назавжди видаляти відправлені повідомлення.</string> + <string name="message_deletion_prohibited_in_chat">Назавжди видалення повідомлень заборонене в цій групі.</string> + <string name="voice_messages_are_prohibited">Голосові повідомлення заборонені в цій групі.</string> <string name="group_members_can_add_message_reactions">Учасники групи можуть додавати реакції на повідомлення.</string> - <string name="message_reactions_are_prohibited">Реакції на повідомлення в цій групі заборонені.</string> + <string name="message_reactions_are_prohibited">Реакції на повідомлення заборонені в цій групі.</string> <string name="ttl_hour">%d година</string> <string name="ttl_week">%d тиждень</string> - <string name="ttl_weeks">%d тижнів</string> + <string name="ttl_weeks">%d тижні</string> <string name="ttl_w">%dw</string> - <string name="feature_offered_item_with_param">запропонував %s: %2s</string> - <string name="v4_2_auto_accept_contact_requests_desc">З необов’язковим вітальним повідомленням.</string> - <string name="v4_3_improved_privacy_and_security_desc">Приховати екран програми в останніх програмах.</string> - <string name="v4_4_disappearing_messages">Зникнення повідомлень</string> + <string name="feature_offered_item_with_param">запропоновано %s: %2s</string> + <string name="v4_2_auto_accept_contact_requests_desc">З опційним вітанням.</string> + <string name="v4_3_improved_privacy_and_security_desc">Приховуйте екран додатка в останніх програмах.</string> + <string name="v4_4_disappearing_messages">Самознищувальні повідомлення</string> <string name="v4_4_live_messages_desc">Одержувачі бачать оновлення, коли ви їх вводите.</string> - <string name="v4_5_transport_isolation">Транспортна ізоляція</string> - <string name="v4_5_private_filenames_descr">Для захисту часового поясу у файлах зображень/голосу використовується UTC.</string> - <string name="v4_5_italian_interface_descr">Дякуємо користувачам - зробіть свій внесок через Weblate!</string> + <string name="v4_5_transport_isolation">Ізоляція транспорту</string> + <string name="v4_5_private_filenames_descr">Для захисту часового поясу файли зображень/голосу використовують UTC.</string> + <string name="v4_5_italian_interface_descr">Дякуємо користувачам – приєднуйтеся через Weblate!</string> <string name="v4_6_group_moderation_descr">Тепер адміністратори можуть: -\n- видалити повідомлення учасників. -\n- відключити учасників (роль \"спостерігач\")</string> - <string name="v4_6_group_welcome_message_descr">Налаштуйте повідомлення, яке показуватиметься новим користувачам!</string> - <string name="v4_6_reduced_battery_usage">Подальше зменшення використання акумулятора</string> - <string name="v4_6_reduced_battery_usage_descr">Незабаром буде ще більше покращень!</string> - <string name="v5_0_large_files_support">Відео та файли до 1 Гб</string> +\n- видаляти повідомлення учасників. +\n- вимикати учасників (роль спостерігач)</string> + <string name="v4_6_group_welcome_message_descr">Встановіть повідомлення, яке показується новим учасникам!</string> + <string name="v4_6_reduced_battery_usage">Додатково зменшено використання батареї</string> + <string name="v4_6_reduced_battery_usage_descr">Більше поліпшень незабаром!</string> + <string name="v5_0_large_files_support">Відео та файли до 1 ГБ</string> <string name="v5_0_polish_interface">Польський інтерфейс</string> - <string name="v5_0_polish_interface_descr">Дякуємо користувачам - зробіть свій внесок через Weblate!</string> + <string name="v5_0_polish_interface_descr">Дякуємо користувачам – приєднуйтеся через Weblate!</string> <string name="v5_1_message_reactions">Реакції на повідомлення</string> - <string name="v5_1_message_reactions_descr">Нарешті, вони у нас є! 🚀</string> + <string name="v5_1_message_reactions_descr">Нарешті, ми їх маємо! 🚀</string> <string name="v5_1_custom_themes_descr">Налаштовуйте та діліться кольоровими темами.</string> - <string name="whats_new_thanks_to_users_contribute_weblate">Дякуємо користувачам - зробіть свій внесок через Weblate!</string> - <string name="custom_time_unit_seconds">секунд</string> - <string name="custom_time_unit_weeks">тижнів</string> + <string name="whats_new_thanks_to_users_contribute_weblate">Дякуємо користувачам – приєднуйтеся через Weblate!</string> + <string name="custom_time_unit_seconds">секунди</string> + <string name="custom_time_unit_weeks">тижні</string> <string name="custom_time_unit_months">місяці</string> - <string name="you_are_already_connected_to_vName_via_this_link">Ви вже підключені до %1$s.</string> + <string name="you_are_already_connected_to_vName_via_this_link">Ви вже підключені до %1$s через це посилання.</string> <string name="settings_section_title_incognito">Режим інкогніто</string> <string name="conn_stats_section_title_servers">СЕРВЕРИ</string> - <string name="save_welcome_message_question">Зберегти привітальне повідомлення\?</string> + <string name="save_welcome_message_question">Зберегти ласкаво просимо?</string> <string name="receiving_via">Отримання через</string> - <string name="muted_when_inactive">Вимкнено, коли неактивний!</string> + <string name="muted_when_inactive">Приглушено, коли неактивно!</string> <string name="delete_profile">Видалити профіль</string> <string name="incognito">Інкогніто</string> - <string name="incognito_info_allows">Це дозволяє мати багато анонімних з\'єднань без будь-яких спільних даних між ними в одному профілі чату.</string> + <string name="incognito_info_allows">Це дозволяє мати багато анонімних з\'єднань без будь-яких загальних даних між ними в одному чат-профілі.</string> <string name="theme_simplex">SimpleX</string> - <string name="only_your_contact_can_send_disappearing">Тільки ваш контакт може надсилати зникаючі повідомлення.</string> - <string name="chat_preferences_on">увімкнути</string> - <string name="ttl_hours">%d годин</string> - <string name="error_deleting_pending_contact_connection">Помилка видалення очікуваного з\'єднання контакту</string> + <string name="only_your_contact_can_send_disappearing">Тільки ваш контакт може надсилати повідомлення, які зникають.</string> + <string name="chat_preferences_on">увімк</string> + <string name="ttl_hours">%d години</string> + <string name="error_deleting_pending_contact_connection">Помилка видалення очікуючого з\'єднання з контактом</string> <string name="error_loading_details">Помилка завантаження деталей</string> - <string name="connection_error_auth_desc">Якщо ваш контакт не видалив з\'єднання або якщо це посилання вже використовувалося, це може бути помилкою - будь ласка, повідомте про це. -\nЩоб підключитися, попросіть вашого контакта створити інше посилання і перевірте, чи маєте ви стабільне з\'єднання з мережею.</string> + <string name="connection_error_auth_desc">Якщо ваш контакт не видалив з\'єднання або це посилання вже використано, це може бути помилкою - будь ласка, повідомте про це. +\nДля підключення попросіть вашого контакту створити інше посилання на з\'єднання та перевірте стабільність мережевого підключення.</string> <string name="error_deleting_contact">Помилка видалення контакту</string> <string name="error_deleting_group">Помилка видалення групи</string> - <string name="smp_server_test_disconnect">Від\'єднати</string> + <string name="smp_server_test_disconnect">Відключити</string> <string name="smp_server_test_secure_queue">Безпечна черга</string> <string name="smp_server_test_delete_queue">Видалити чергу</string> - <string name="please_check_correct_link_and_maybe_ask_for_a_new_one">Будь ласка, переконайтеся, що ви використали правильне посилання, або попросіть свого контакта надіслати вам інше.</string> - <string name="turn_off_battery_optimization"><![CDATA[Щоб використовувати його, <b>дозвольте SimpleX працювати у фоновому режимі</b> у наступному діалоговому вікні. \u0020В іншому випадку сповіщення буде вимкнено.]]></string> + <string name="please_check_correct_link_and_maybe_ask_for_a_new_one">Будь ласка, перевірте, що ви використали правильне посилання або попросіть вашого контакту вислати інше.</string> + <string name="turn_off_battery_optimization"><![CDATA[Щоб його використовувати, будь ласка, <b>дозвольте SimpleX працювати в фоновому режимі</b> в наступному діалозі. В іншому випадку сповіщення будуть вимкнені.]]></string> <string name="icon_descr_instant_notifications">Миттєві сповіщення</string> - <string name="notification_preview_somebody">Контакт приховано:</string> + <string name="notification_preview_somebody">Контакт прихований:</string> <string name="notification_preview_new_message">нове повідомлення</string> <string name="edit_verb">Редагувати</string> <string name="info_menu">Інформація</string> - <string name="sent_message">Надіслано повідомлення</string> - <string name="auth_you_will_be_required_to_authenticate_when_you_start_or_resume">Вам потрібно буде пройти автентифікацію при запуску або відновленні програми після 30 секунд роботи у фоновому режимі.</string> - <string name="received_message">Отримано повідомлення</string> + <string name="sent_message">Відправлене повідомлення</string> + <string name="auth_you_will_be_required_to_authenticate_when_you_start_or_resume">Вам буде потрібно пройти аутентифікацію при запуску або відновленні програми через 30 секунд у фоновому режимі.</string> + <string name="received_message">Отримане повідомлення</string> <string name="edit_history">Історія</string> <string name="reveal_verb">Розкрити</string> <string name="hide_verb">Приховати</string> - <string name="moderate_verb">Редагування</string> + <string name="moderate_verb">Модерувати</string> <string name="delete_message__question">Видалити повідомлення\?</string> - <string name="delete_message_cannot_be_undone_warning">Повідомлення буде видалено - це неможливо скасувати!</string> - <string name="icon_descr_sent_msg_status_sent">надісланий</string> - <string name="voice_messages_prohibited">Голосові повідомлення заборонені!</string> + <string name="delete_message_cannot_be_undone_warning">Повідомлення буде видалено - цю дію неможливо скасувати!</string> + <string name="icon_descr_sent_msg_status_sent">відправлено</string> + <string name="voice_messages_prohibited">Заборонено голосові повідомлення!</string> <string name="send_disappearing_message_send">Надіслати</string> <string name="confirm_verb">Підтвердити</string> - <string name="send_disappearing_message_custom_time">Індивідуальний час</string> - <string name="share_one_time_link">Створіть одноразове посилання-запрошення</string> - <string name="scan_QR_code">Відскануйте QR-код</string> + <string name="send_disappearing_message_custom_time">Інший час</string> + <string name="share_one_time_link">Створити одноразове запрошення</string> + <string name="scan_QR_code">Сканувати QR-код</string> <string name="gallery_image_button">Зображення</string> <string name="gallery_video_button">Відео</string> - <string name="connection_you_accepted_will_be_cancelled">Прийняте вами з\'єднання буде скасовано!</string> - <string name="alert_title_contact_connection_pending">Контакт ще не підключено!</string> + <string name="connection_you_accepted_will_be_cancelled">Прийняте вами з\'єднання буде скасоване!</string> + <string name="alert_title_contact_connection_pending">Контакт ще не підключений!</string> <string name="smp_servers_test_servers">Тестові сервери</string> <string name="smp_servers_save">Зберегти сервери</string> <string name="smp_servers_your_server">Ваш сервер</string> - <string name="smp_servers_test_failed">Тест сервера завершився невдало!</string> + <string name="smp_servers_test_failed">Тест сервера не вдався!</string> <string name="smp_servers_test_some_failed">Деякі сервери не пройшли тест:</string> <string name="smp_servers_use_server">Використовувати сервер</string> - <string name="ensure_ICE_server_address_are_correct_format_and_unique">Переконайтеся, що адреси серверів WebRTC ICE мають правильний формат, розділені рядками та не дублюються.</string> - <string name="network_disable_socks_info">Якщо ви підтвердите, сервери обміну повідомленнями зможуть бачити вашу IP-адресу, а ваш провайдер - до яких серверів ви підключаєтеся.</string> - <string name="network_use_onion_hosts_no_desc">Onion хости не використовуватимуться.</string> - <string name="network_session_mode_transport_isolation">Транспортна ізоляція</string> - <string name="customize_theme_title">Налаштувати тему</string> - <string name="share_address_with_contacts_question">Поділіться адресою з контактами\?</string> - <string name="callstatus_connecting">З\'єднувальний дзвінок…</string> - <string name="we_do_not_store_contacts_or_messages_on_servers">Ми не зберігаємо жодних ваших контактів чи повідомлень (після доставки) на серверах.</string> - <string name="callstate_waiting_for_answer">в очікуванні відповіді…</string> + <string name="ensure_ICE_server_address_are_correct_format_and_unique">Переконайтеся, що адреси серверів WebRTC ICE вказані в правильному форматі, розділені по рядках і не повторюються.</string> + <string name="network_disable_socks_info">Якщо ви підтвердите, сервери обміну повідомленнями матимуть можливість бачити ваш IP-адресу, а ваш постачальник - які саме сервери ви використовуєте для підключення.</string> + <string name="network_use_onion_hosts_no_desc">.Onion-хости не будуть використовуватися.</string> + <string name="network_session_mode_transport_isolation">Ізоляція транспорту</string> + <string name="customize_theme_title">Налаштування теми</string> + <string name="share_address_with_contacts_question">Поділитися адресою з контактами?</string> + <string name="callstatus_connecting">підключення дзвінка…</string> + <string name="we_do_not_store_contacts_or_messages_on_servers">Ми не зберігаємо жодні з ваших контактів чи повідомлень (після доставки) на серверах.</string> + <string name="callstate_waiting_for_answer">очікування відповіді…</string> <string name="how_it_works">Як це працює</string> - <string name="icon_descr_video_call">відеодзвінок</string> + <string name="icon_descr_video_call">відеовиклик</string> <string name="show_call_on_lock_screen">Показати</string> <string name="no_call_on_lock_screen">Вимкнути</string> - <string name="relay_server_if_necessary">Сервер ретрансляції використовується лише за необхідності. Інша сторона може спостерігати за вашою IP-адресою.</string> - <string name="alert_text_decryption_error_n_messages_failed_to_decrypt">%1$d повідомлення не вдалося розшифрувати.</string> - <string name="alert_text_decryption_error_too_many_skipped">%1$d повідомлення пропущені.</string> - <string name="alert_text_fragment_please_report_to_developers">Будь ласка, повідомте про це розробникам.</string> - <string name="send_link_previews">Надіслати попередній перегляд за посиланням</string> - <string name="lock_after">Блокування після</string> - <string name="submit_passcode">Представити</string> + <string name="relay_server_if_necessary">Реле-сервер використовується лише у необхідних випадках. Інша сторона може спостерігати за вашою IP-адресою.</string> + <string name="alert_text_decryption_error_n_messages_failed_to_decrypt">%1$d повідомлень не вдалося розшифрувати.</string> + <string name="alert_text_decryption_error_too_many_skipped">%1$d пропущено повідомлень.</string> + <string name="alert_text_fragment_please_report_to_developers">Будь ласка, повідомте розробникам про це.</string> + <string name="send_link_previews">Надсилати попередні перегляди посилань</string> + <string name="lock_after">Блокувати через</string> + <string name="submit_passcode">Підтвердити</string> <string name="enabled_self_destruct_passcode">Увімкнути пароль самознищення</string> <string name="change_self_destruct_mode">Змінити режим самознищення</string> <string name="incorrect_passcode">Неправильний пароль</string> @@ -880,581 +876,641 @@ <string name="change_self_destruct_passcode">Змінити пароль самознищення</string> <string name="self_destruct_passcode">Пароль самознищення</string> <string name="enable_self_destruct">Увімкнути самознищення</string> - <string name="self_destruct_new_display_name">Нове ім\'я для відображення:</string> - <string name="if_you_enter_self_destruct_code">Якщо ви введете пароль самознищення під час відкриття програми:</string> - <string name="if_you_enter_passcode_data_removed">Якщо ви введете цей пароль при відкритті програми, всі дані програми будуть безповоротно видалені!</string> + <string name="self_destruct_new_display_name">Нове ім\'я профілю:</string> + <string name="if_you_enter_self_destruct_code">Якщо ви введете пароль самознищення при відкритті застосунку:</string> + <string name="if_you_enter_passcode_data_removed">Якщо ви введете цей пароль при відкритті застосунку, всі дані застосунку буде неможливо відновити!</string> <string name="set_passcode">Встановити пароль</string> - <string name="delete_chat_profile_action_cannot_be_undone_warning">Цю дію неможливо скасувати - ваш профіль, контакти, повідомлення та файли будуть безповоротно втрачені.</string> - <string name="chat_database_deleted">Видалено базу даних чату</string> - <string name="no_received_app_files">Немає отриманих або відправлених файлів</string> + <string name="delete_chat_profile_action_cannot_be_undone_warning">Цю дію неможливо відмінити - ваш профіль, контакти, повідомлення та файли буде втрачено безповоротно.</string> + <string name="chat_database_deleted">Базу даних чату видалено</string> + <string name="no_received_app_files">Немає отриманих або відісланих файлів</string> <string name="info_row_received_at">Отримано о</string> - <string name="info_row_deleted_at">Видалено за</string> - <string name="share_text_received_at">Отримано за: %s</string> - <string name="share_text_sent_at">Надіслано: %s</string> - <string name="share_text_deleted_at">Видалено за: %s</string> - <string name="current_version_timestamp">%s (поточний)</string> + <string name="info_row_deleted_at">Видалено о</string> + <string name="share_text_received_at">Отримано о: %s</string> + <string name="share_text_sent_at">Надіслано о: %s</string> + <string name="share_text_deleted_at">Видалено о: %s</string> + <string name="current_version_timestamp">%s (поточне)</string> <string name="ttl_h">%dh</string> <string name="ttl_day">%d день</string> <string name="ttl_days">%d днів</string> <string name="feature_cancelled_item">скасовано %s</string> - <string name="run_chat_section">ЗАПУСТИТИ ЧАТ</string> - <string name="database_passphrase">Ключова фраза бази даних</string> - <string name="export_database">Експорт бази даних</string> + <string name="run_chat_section">ЗАПУСК ЧАТУ</string> + <string name="database_passphrase">Пароль бази даних</string> + <string name="export_database">Експортувати базу даних</string> <string name="delete_files_and_media_all">Видалити всі файли</string> <string name="delete_messages_after">Видаляйте повідомлення після</string> <string name="enable_automatic_deletion_question">Увімкнути автоматичне видалення повідомлень\?</string> - <string name="should_be_at_least_one_visible_profile">Повинен бути принаймні один видимий профіль користувача.</string> <string name="v4_6_hidden_chat_profiles">Приховані профілі чату</string> - <string name="v4_6_group_welcome_message">Привітальне повідомлення групи</string> - <string name="v4_6_chinese_spanish_interface_descr">Дякуємо користувачам - зробіть свій внесок через Weblate!</string> - <string name="la_lock_mode">Режим SimpleX Lock</string> - <string name="la_lock_mode_system">Аутентифікація системи</string> - <string name="to_protect_privacy_simplex_has_ids_for_queues">Для захисту конфіденційності, замість ідентифікаторів користувачів, які використовуються на всіх інших платформах, SimpleX має ідентифікатори для черг повідомлень, окремі для кожного з ваших контактів.</string> - <string name="onboarding_notifications_mode_off">Коли додаток працює</string> - <string name="onboarding_notifications_mode_periodic">Періодичні</string> - <string name="status_contact_has_no_e2e_encryption">контакт не має шифрування e2e</string> + <string name="v4_6_group_welcome_message">Повідомлення вітання групи</string> + <string name="v4_6_chinese_spanish_interface_descr">Дякуємо користувачам – приєднуйтеся через Weblate!</string> + <string name="la_lock_mode">Режим блокування SimpleX</string> + <string name="la_lock_mode_system">Системна аутентифікація</string> + <string name="to_protect_privacy_simplex_has_ids_for_queues">Для захисту приватності, замість ідентифікаторів користувачів, які використовуються всіма іншими платформами, у SimpleX є ідентифікатори черг повідомлень, окремі для кожного з ваших контактів.</string> + <string name="onboarding_notifications_mode_off">Коли додаток запущено</string> + <string name="onboarding_notifications_mode_periodic">Періодично</string> + <string name="status_contact_has_no_e2e_encryption">контакт не має зашифрування e2e</string> <string name="enable_lock">Увімкнути блокування</string> <string name="passcode_not_changed">Пароль не змінено!</string> - <string name="change_lock_mode">Зміна режиму блокування</string> + <string name="change_lock_mode">Змінити режим блокування</string> <string name="stop_chat_to_enable_database_actions">Зупиніть чат, щоб увімкнути дії з базою даних.</string> <string name="restart_the_app_to_create_a_new_chat_profile">Перезапустіть додаток, щоб створити новий профіль чату.</string> - <string name="delete_files_and_media_for_all_users">Видалення файлів для всіх профілів чату</string> - <string name="delete_files_and_media_question">Видаляти файли та медіа\?</string> - <string name="total_files_count_and_size">%d файл(и) загальним розміром %s</string> - <string name="database_is_not_encrypted">Ваша база даних чату не зашифрована - встановіть парольну фразу, щоб захистити її.</string> - <string name="impossible_to_recover_passphrase"><![CDATA[<b>Зверніть увагу</b>: ви НЕ зможете відновити або змінити парольну фразу, якщо її втратите.]]></string> + <string name="delete_files_and_media_for_all_users">Видалити файли для всіх профілів чату</string> + <string name="delete_files_and_media_question">Видалити файли та медіа?</string> + <string name="total_files_count_and_size">%d файл(ів) обсягом %s</string> + <string name="database_is_not_encrypted">Ваша база даних чату не зашифрована - встановіть ключову фразу для її захисту.</string> + <string name="impossible_to_recover_passphrase"><![CDATA[<b>Зверніть увагу</b>: ви НЕ зможете відновити або змінити ключову фразу, якщо ви її втратите.]]></string> <string name="theme_system">Система</string> <string name="incompatible_database_version">Несумісна версія бази даних</string> <string name="confirm_database_upgrades">Підтвердити оновлення бази даних</string> - <string name="invalid_migration_confirmation">Недійсне підтвердження перенесення</string> - <string name="mtr_error_no_down_migration">версія бази даних новіша, ніж додаток, але без міграції вниз: %s</string> - <string name="mtr_error_different">інша міграція в додатку/базі даних: %s / %s</string> + <string name="invalid_migration_confirmation">Недійсне підтвердження міграції</string> + <string name="mtr_error_no_down_migration">Версія бази даних новіша, ніж додаток, але немає можливості знизити до: %s</string> + <string name="mtr_error_different">Різна міграція в додатку/базі даних: %s / %s</string> <string name="database_migrations">Міграції: %s</string> - <string name="alert_title_group_invitation_expired">Термін дії запрошення закінчився!</string> - <string name="you_will_stop_receiving_messages_from_this_group_chat_history_will_be_preserved">Ви більше не будете отримувати повідомлення від цієї групи. Історія чату буде збережена.</string> + <string name="alert_title_group_invitation_expired">Запрошення закінчилось!</string> + <string name="you_will_stop_receiving_messages_from_this_group_chat_history_will_be_preserved">Ви перестанете отримувати повідомлення від цієї групи. Історія чату буде збережена.</string> <string name="icon_descr_add_members">Запросити учасників</string> <string name="icon_descr_group_inactive">Група неактивна</string> <string name="snd_group_event_member_deleted">ви видалили %1$s</string> - <string name="tap_to_activate_profile">Натисніть, щоб активувати профіль.</string> - <string name="cant_delete_user_profile">Не можу видалити профіль користувача!</string> - <string name="prohibit_sending_voice">Заборонити надсилання голосових повідомлень.</string> - <string name="group_members_can_send_disappearing">Учасники групи можуть надсилати зникаючі повідомлення.</string> + <string name="tap_to_activate_profile">Торкніться для активації профілю.</string> + <string name="prohibit_sending_voice">Забороняйте надсилання голосових повідомлень.</string> + <string name="group_members_can_send_disappearing">Учасники групи можуть надсилати самознищувальні повідомлення.</string> <string name="ttl_min">%d хв</string> - <string name="v4_5_reduced_battery_usage">Зменшення використання акумулятора</string> + <string name="v4_5_reduced_battery_usage">Зменшене споживання енергії батареї</string> <string name="edit_image">Редагувати зображення</string> - <string name="integrity_msg_duplicate">дублююче повідомлення</string> - <string name="unknown_database_error_with_info">Невідома помилка в базі даних: %s</string> - <string name="enter_passphrase">Введіть пароль…</string> + <string name="integrity_msg_duplicate">дубльоване повідомлення</string> + <string name="unknown_database_error_with_info">Невідома помилка бази даних: %s</string> + <string name="enter_passphrase">Введіть ключову фразу…</string> <string name="open_chat">Відкрити чат</string> - <string name="youve_accepted_group_invitation_connecting_to_inviting_group_member">Ви приєдналися до цієї групи. Підключення до запрошеного учасника групи.</string> - <string name="rcv_group_event_updated_group_profile">оновлений профіль групи</string> + <string name="youve_accepted_group_invitation_connecting_to_inviting_group_member">Ви приєдналися до цієї групи. З\'єднання з учасником, який вас запрошував.</string> + <string name="rcv_group_event_updated_group_profile">оновлено профіль групи</string> <string name="snd_conn_event_switch_queue_phase_changing">змінює адресу…</string> <string name="leave_group_button">Залишити</string> <string name="group_member_role_observer">спостерігач</string> <string name="member_info_section_title_member">УЧАСНИК</string> <string name="incognito_info_protects">Режим інкогніто захищає вашу конфіденційність, використовуючи новий випадковий профіль для кожного контакту.</string> - <string name="v4_5_reduced_battery_usage_descr">Незабаром буде ще більше покращень!</string> - <string name="only_group_owners_can_enable_voice">Тільки власники груп можуть вмикати голосові повідомлення.</string> + <string name="v4_5_reduced_battery_usage_descr">Більше поліпшень незабаром!</string> + <string name="only_group_owners_can_enable_voice">Тільки власники груп можуть увімкнути голосові повідомлення.</string> <string name="reject_contact_button">Відхилити</string> <string name="clear_chat_question">Очистити чат\?</string> - <string name="image_descr_link_preview">посилання для попереднього перегляду зображення</string> + <string name="image_descr_link_preview">зображення попереднього перегляду посилання</string> <string name="icon_descr_cancel_link_preview">скасувати попередній перегляд посилання</string> <string name="icon_descr_settings">Налаштування</string> - <string name="network_use_onion_hosts_no_desc_in_alert">Onion хости не використовуватимуться.</string> + <string name="network_use_onion_hosts_no_desc_in_alert">Хости .onion не будуть використовуватися.</string> <string name="icon_descr_call_progress">Виклик у процесі</string> - <string name="database_error">Помилка в базі даних</string> + <string name="database_error">Помилка бази даних</string> <string name="restore_database_alert_confirm">Відновити</string> - <string name="group_member_status_connected">підключений</string> + <string name="group_member_status_connected">підключено</string> <string name="group_member_status_creator">творець</string> <string name="group_member_status_announced">підключення (оголошено)</string> <string name="ttl_month">%d місяць</string> - <string name="v4_5_multiple_chat_profiles_descr">Різні імена, аватарки та транспортна ізоляція.</string> + <string name="v4_5_multiple_chat_profiles_descr">Різні імена, аватари та ізоляція транспорту.</string> <string name="v4_5_private_filenames">Приватні імена файлів</string> <string name="v4_3_improved_server_configuration">Покращена конфігурація сервера</string> <string name="error_saving_user_password">Помилка збереження пароля користувача</string> - <string name="alert_title_cant_invite_contacts_descr">Ви використовуєте профіль анонімного перегляду для цієї групи – щоб запобігти спільному доступу до вашого основного профілю, запрошення контактів заборонено</string> + <string name="alert_title_cant_invite_contacts_descr">Ви використовуєте анонімний профіль для цієї групи - для запобігання розголошенню вашого основного профілю запрошення контактів не дозволено.</string> <string name="you_joined_this_group">Ви приєдналися до цієї групи</string> - <string name="la_could_not_be_verified">Вас не вдалося перевірити; будь ласка спробуйте ще раз.</string> - <string name="la_no_app_password">Немає пароля додатку</string> - <string name="la_enter_app_passcode">Введіть пароль</string> - <string name="la_current_app_passcode">Поточний пароль</string> - <string name="la_lock_mode_passcode">Введення пароля</string> - <string name="la_change_app_passcode">Змінити пароль</string> + <string name="la_could_not_be_verified">Вашу особу не вдалося підтвердити; спробуйте ще раз.</string> + <string name="la_no_app_password">Немає коду доступу до додатка</string> + <string name="la_enter_app_passcode">Введіть код доступу</string> + <string name="la_current_app_passcode">Поточний код доступу</string> + <string name="la_lock_mode_passcode">Введення коду доступу</string> + <string name="la_change_app_passcode">Змінити код доступу</string> <string name="la_immediately">Негайно</string> - <string name="la_seconds">%d секунд</string> - <string name="la_minutes">%d хвилин</string> + <string name="la_seconds">%d секунд(и)</string> + <string name="la_minutes">%d хвилин(и)</string> <string name="message_delivery_error_title">Помилка доставки повідомлення</string> <string name="network_session_mode_user">Профіль чату</string> <string name="reject">Відхилити</string> - <string name="relay_server_protects_ip">Сервер ретрансляції захищає вашу IP-адресу, але він може спостерігати за тривалістю дзвінка.</string> + <string name="relay_server_protects_ip">Реле-сервер захищає ваш IP-адресу, але може відслідковувати тривалість виклику.</string> <string name="lock_mode">Режим блокування</string> <string name="passcode_changed">Пароль змінено!</string> <string name="la_mode_system">Система</string> <string name="la_mode_passcode">Пароль</string> <string name="passcode_set">Пароль встановлено!</string> - <string name="upgrade_and_open_chat">Оновіть і відкрийте чат</string> - <string name="database_downgrade_warning">Попередження: ви можете втратити деякі дані!</string> - <string name="you_can_start_chat_via_setting_or_by_restarting_the_app">Ви можете розпочати чат через Налаштування програми / База даних або перезапустивши програму.</string> - <string name="you_sent_group_invitation">Ви надіслали запрошення до групи</string> - <string name="you_are_invited_to_group">Вас запросили до групи</string> - <string name="group_invitation_expired">Термін дії групового запрошення закінчився</string> - <string name="icon_descr_contact_checked">Контакт перевірено</string> - <string name="invite_prohibited_description">Ви намагаєтеся запросити контакт, з яким ви поділилися анонімним профілем, до групи, у якій ви використовуєте свій основний профіль</string> - <string name="error_creating_link_for_group">Помилка створення посилання на групу</string> + <string name="upgrade_and_open_chat">Оновити та відкрити чат</string> + <string name="database_downgrade_warning">Попередження: можливо, ви втратите деякі дані!</string> + <string name="you_can_start_chat_via_setting_or_by_restarting_the_app">Ви можете запустити чат через налаштування програми або перезапустивши додаток.</string> + <string name="you_sent_group_invitation">Ви відправили запрошення в групу</string> + <string name="you_are_invited_to_group">Вас запрошено в групу</string> + <string name="group_invitation_expired">Запрошення в групу закінчилось</string> + <string name="icon_descr_contact_checked">Контакт відмічено</string> + <string name="invite_prohibited_description">Ви намагаєтеся запросити контакт, з яким ви поділилися інкогніто-профілем, до групи, в якій ви використовуєте основний профіль</string> + <string name="error_creating_link_for_group">Помилка при створенні посилання на групу</string> <string name="section_title_for_console">ДЛЯ КОНСОЛІ</string> - <string name="member_will_be_removed_from_group_cannot_be_undone">Учасник буде видалений з групи - це неможливо скасувати!</string> + <string name="member_will_be_removed_from_group_cannot_be_undone">Учасника буде вилучено з групи - цю дію неможливо скасувати!</string> <string name="change_role">Змінити роль</string> - <string name="network_options_revert">Повернути</string> - <string name="you_will_still_receive_calls_and_ntfs">Ви все одно отримуватимете дзвінки та сповіщення від вимкнених профілів, якщо вони активні.</string> - <string name="ttl_months">%d місяців</string> - <string name="ttl_mth">%d міс</string> - <string name="v4_4_disappearing_messages_desc">Надіслані повідомлення будуть видалені через встановлений час.</string> + <string name="network_options_revert">Відновити</string> + <string name="you_will_still_receive_calls_and_ntfs">Ви все ще отримуватимете дзвінки та сповіщення від приглушених профілів, коли вони активні.</string> + <string name="ttl_months">%d місяці</string> + <string name="ttl_mth">%dmth</string> + <string name="v4_4_disappearing_messages_desc">Надіслані повідомлення будуть видалені після встановленого часу.</string> <string name="opening_database">Відкриття бази даних…</string> - <string name="error_setting_address">Помилка налаштування адреси</string> - <string name="smp_server_test_connect">Підключіться</string> - <string name="la_please_remember_to_store_password">Будь ласка, запам\'ятайте або надійно збережіть його - втрачений пароль неможливо відновити!</string> + <string name="error_setting_address">Помилка встановлення адреси</string> + <string name="smp_server_test_connect">Підключити</string> + <string name="la_please_remember_to_store_password">Будь ласка, запам\'ятайте або збережіть його надійно - немає можливості відновлення втраченого пароля!</string> <string name="auth_open_chat_profiles">Відкрити профілі чату</string> - <string name="icon_descr_waiting_for_video">В очікуванні відео</string> - <string name="waiting_for_file">Очікування файлу</string> + <string name="icon_descr_waiting_for_video">Очікування на відео</string> + <string name="waiting_for_file">Очікування на файл</string> <string name="voice_message_with_duration">Голосове повідомлення (%1$s)</string> <string name="notifications">Сповіщення</string> <string name="delete_contact_question">Видалити контакт\?</string> - <string name="icon_descr_cancel_live_message">Скасувати повідомлення в прямому ефірі</string> + <string name="icon_descr_cancel_live_message">Скасувати живе повідомлення</string> <string name="reset_verb">Скинути</string> - <string name="no_details">без подробиць</string> + <string name="no_details">без деталей</string> <string name="connect_via_link_or_qr">Підключитися за посиланням / QR-кодом</string> - <string name="clear_verb">Чисто</string> + <string name="clear_verb">Очистити</string> <string name="invalid_QR_code">Неправильний QR-код</string> - <string name="you_will_be_connected_when_your_contacts_device_is_online">Ви будете з\'єднані, коли пристрій вашого контакту буде в мережі, будь ласка, зачекайте або перевірте пізніше!</string> - <string name="you_wont_lose_your_contacts_if_delete_address">Ви не втратите свої контакти, якщо згодом видалите свою адресу.</string> - <string name="you_can_accept_or_reject_connection">Коли люди звертаються із запитом на підключення, ви можете прийняти або відхилити його.</string> - <string name="read_more_in_user_guide_with_link"><![CDATA[Докладніше в <font color="#0088ff">Посібнику користувача</font>.]]></string> - <string name="simplex_address">Адреса SimpleX</string> - <string name="clear_verification">Очистити верифікацію</string> + <string name="you_will_be_connected_when_your_contacts_device_is_online">Вас підключать, коли пристрій вашого контакту буде в мережі, зачекайте або перевірте пізніше!</string> + <string name="you_wont_lose_your_contacts_if_delete_address">Ви не втратите свої контакти, якщо ви пізніше видалите свою адресу.</string> + <string name="you_can_accept_or_reject_connection">Коли люди просять про з\'єднання, ви можете його прийняти чи відхилити.</string> + <string name="read_more_in_user_guide_with_link"><![CDATA[Докладніше читайте в <font color="#0088ff">Посібнику користувача</font>.]]></string> + <string name="simplex_address">SimpleX-адреса</string> + <string name="clear_verification">Очистити перевірку</string> <string name="is_verified">%s перевірено</string> <string name="is_not_verified">%s не перевірено</string> - <string name="send_us_an_email">Надішліть нам електронний лист</string> + <string name="send_us_an_email">Надішліть нам електронного листа</string> <string name="smp_servers_test_server">Тестовий сервер</string> <string name="smp_save_servers_question">Зберегти сервери\?</string> <string name="your_ICE_servers">Ваші сервери ICE</string> <string name="save_servers_button">Зберегти</string> - <string name="network_socks_proxy_settings">Налаштування проксі SOCKS</string> - <string name="network_socks_toggle_use_socks_proxy">Використовуйте проксі SOCKS</string> + <string name="network_socks_proxy_settings">Налаштування SOCKS-проксі</string> + <string name="network_socks_toggle_use_socks_proxy">Використовувати SOCKS-проксі</string> <string name="network_proxy_port">порт %d</string> <string name="host_verb">Хост</string> <string name="port_verb">Порт</string> - <string name="network_use_onion_hosts_required">Потрібно</string> - <string name="theme_colors_section_title">КОЛЬОРИ ТЕМИ</string> - <string name="create_address_and_let_people_connect">Створіть адресу, щоб люди могли з вами зв\'язатися.</string> - <string name="your_contacts_will_remain_connected">Ваші контакти залишаться на зв’язку.</string> - <string name="create_simplex_address">Створіть адресу SimpleX</string> - <string name="profile_update_will_be_sent_to_contacts">Оновлення профілю буде надіслано вашим контактам.</string> - <string name="stop_sharing_address">Припинити ділитися адресою\?</string> - <string name="stop_sharing">Припиніть ділитися</string> - <string name="enter_welcome_message_optional">Введіть вітальне повідомлення... (необов\'язково)</string> + <string name="network_use_onion_hosts_required">Обов\'язково</string> + <string name="theme_colors_section_title">КОЛОРИ ТЕМИ</string> + <string name="create_address_and_let_people_connect">Створіть адресу, щоб дозволити людям підключатися до вас.</string> + <string name="your_contacts_will_remain_connected">Ваші контакти залишаться підключеними.</string> + <string name="create_simplex_address">Створити SimpleX-адресу</string> + <string name="profile_update_will_be_sent_to_contacts">Оновлення профілю буде відправлено вашим контактам.</string> + <string name="stop_sharing_address">Зупинити поділ адреси?</string> + <string name="stop_sharing">Зупинити поділ</string> + <string name="enter_welcome_message_optional">Введіть текст привітання... (необов\'язково)</string> <string name="save_settings_question">Зберегти налаштування\?</string> - <string name="save_auto_accept_settings">Зберегти налаштування автоприйняття</string> + <string name="save_auto_accept_settings">Зберегти налаштування автоприйому</string> <string name="email_invite_body">Привіт! -\nЗв\'яжіться зі мною через SimpleX Chat: %s</string> +\nПриєднуйтесь до мене через SimpleX Chat: %s</string> <string name="invite_friends">Запросити друзів</string> - <string name="email_invite_subject">Давайте поговоримо в SimpleX Chat</string> + <string name="email_invite_subject">Давайте говорити в SimpleX Chat</string> <string name="continue_to_next_step">Продовжити</string> <string name="dont_create_address">Не створювати адресу</string> - <string name="callstate_received_answer">отримав відповідь…</string> - <string name="callstate_received_confirmation">отримав підтвердження…</string> + <string name="callstate_received_answer">отримано відповідь…</string> + <string name="callstate_received_confirmation">отримано підтвердження…</string> <string name="callstate_connecting">підключення…</string> - <string name="callstate_connected">підключений</string> - <string name="callstate_ended">закінчився</string> - <string name="immune_to_spam_and_abuse">Імунітет до спаму та зловживань</string> - <string name="contact_wants_to_connect_via_call">%1$s хоче зв\'язатися з вами через</string> - <string name="encrypted_video_call">e2e зашифрований відеодзвінок</string> + <string name="callstate_connected">підключено</string> + <string name="callstate_ended">завершено</string> + <string name="immune_to_spam_and_abuse">Стійка до спаму та зловживань</string> + <string name="contact_wants_to_connect_via_call">%1$s хоче підключитися до вас через</string> + <string name="encrypted_video_call">зашифрований e2e відеовиклик</string> <string name="ignore">Ігнорувати</string> - <string name="alert_text_skipped_messages_it_can_happen_when">Це може статися, коли: -\n1. Термін дії повідомлень закінчився в клієнті-відправнику через 2 дні або на сервері через 30 днів. -\n2. Не вдалося розшифрувати повідомлення, тому що ви або ваш контакт використовували стару резервну копію бази даних. -\n3. З\'єднання було скомпрометовано.</string> + <string name="alert_text_skipped_messages_it_can_happen_when">Це може трапитися, коли: +\n1. Повідомлення застаріли відправником через 2 дні або на сервері через 30 днів. +\n2. Помилка розшифровки повідомлення, оскільки ви або ваш контакт використовували застарілу резервну копію бази даних. +\n3. З\'єднання було компрометоване.</string> <string name="alert_title_skipped_messages">Пропущені повідомлення</string> - <string name="protect_app_screen">Захистіть екран програми</string> - <string name="error_stopping_chat">Помилка зупинки чату</string> - <string name="chat_database_imported">Імпорт бази даних чату</string> - <string name="restart_the_app_to_use_imported_chat_database">Перезапустіть програму, щоб використовувати імпортовану базу даних чату.</string> + <string name="protect_app_screen">Захист екрану застосунку</string> + <string name="error_stopping_chat">Помилка при зупинці чату</string> + <string name="chat_database_imported">База даних чату імпортована</string> + <string name="restart_the_app_to_use_imported_chat_database">Перезапустіть додаток, щоб використовувати імпортовану базу даних чату.</string> <string name="file_with_path">Файл: %s</string> - <string name="database_passphrase_is_required">Для відкриття чату потрібно ввести пароль до бази даних.</string> + <string name="database_passphrase_is_required">Для відкриття чату потрібна ключова фраза бази даних.</string> <string name="join_group_question">Приєднатися до групи\?</string> <string name="database_upgrade">Оновлення бази даних</string> <string name="delete_archive">Видалити архів</string> <string name="delete_chat_archive_question">Видалити архів чату\?</string> - <string name="leave_group_question">Покинути групу\?</string> + <string name="leave_group_question">Вийти з групи?</string> <string name="alert_title_no_group">Групу не знайдено!</string> - <string name="alert_message_no_group">Цієї групи більше не існує.</string> - <string name="alert_title_cant_invite_contacts">Неможливо запросити контакти!</string> + <string name="alert_message_no_group">Ця група більше не існує.</string> + <string name="alert_title_cant_invite_contacts">Неможливо запрошувати контакти!</string> <string name="group_member_status_complete">завершено</string> - <string name="button_welcome_message">Вітальне повідомлення</string> - <string name="select_contacts">Виберіть контакти</string> + <string name="button_welcome_message">Привітання</string> + <string name="select_contacts">Вибрати контакти</string> <string name="share_address">Поділитися адресою</string> - <string name="you_can_share_group_link_anybody_will_be_able_to_connect">Ви можете поділитися посиланням або QR-кодом - будь-хто зможе приєднатися до групи. Ви не втратите учасників групи, якщо пізніше видалите її.</string> - <string name="you_can_share_this_address_with_your_contacts">Ви можете поділитися цією адресою зі своїми контактами, щоб вони могли зв\'язатися з %s.</string> - <string name="info_row_local_name">Місцева назва</string> + <string name="you_can_share_group_link_anybody_will_be_able_to_connect">Ви можете поділитися посиланням або QR-кодом - будь-хто зможе приєднатися до групи. Ви не втратите членів групи, якщо потім видалите її.</string> + <string name="you_can_share_this_address_with_your_contacts">Ви можете поділитися цією адресою зі своїми контактами, щоб вони могли підключитися до %s.</string> + <string name="info_row_local_name">Локальна назва</string> <string name="info_row_database_id">Ідентифікатор бази даних</string> <string name="group_welcome_preview">Попередній перегляд</string> - <string name="enter_welcome_message">Введіть вітальне повідомлення…</string> + <string name="enter_welcome_message">Введіть ласкаво просимо…</string> <string name="switch_receiving_address">Змінити адресу отримання</string> <string name="create_secret_group_title">Створити секретну групу</string> - <string name="group_is_decentralized">Повністю децентралізована - видима лише для учасників.</string> - <string name="network_option_tcp_connection_timeout">Тайм-аут підключення TCP</string> - <string name="dont_show_again">Більше не показувати</string> - <string name="color_secondary">Вторинний</string> - <string name="color_surface">Меню та сповіщення</string> - <string name="color_title">Назва</string> - <string name="color_sent_message">Надіслано повідомлення</string> - <string name="color_received_message">Отримано повідомлення</string> + <string name="group_is_decentralized">Повністю децентралізовано - видимо тільки для учасників.</string> + <string name="network_option_tcp_connection_timeout">Тайм-аут з\'єднання TCP</string> + <string name="dont_show_again">Не показувати знову</string> + <string name="color_secondary">Другорядний</string> + <string name="color_surface">Меню та повідомлення</string> + <string name="color_title">Заголовок</string> + <string name="color_sent_message">Надіслане повідомлення</string> + <string name="color_received_message">Отримане повідомлення</string> <string name="chat_preferences_you_allow">Ви дозволяєте</string> <string name="chat_preferences_no">ні</string> - <string name="chat_preferences_off">вимкнено</string> - <string name="set_group_preferences">Встановіть налаштування групи</string> - <string name="your_preferences">Ваші уподобання</string> + <string name="chat_preferences_off">вимк</string> + <string name="set_group_preferences">Встановити налаштування групи</string> + <string name="your_preferences">Ваші налаштування</string> <string name="direct_messages">Прямі повідомлення</string> <string name="icon_descr_server_status_error">Помилка</string> - <string name="add_contact">Посилання на одноразове запрошення</string> - <string name="add_contact_or_create_group">Почніть новий чат</string> + <string name="add_contact">Одноразове запрошення</string> + <string name="add_contact_or_create_group">Створити новий чат</string> <string name="icon_descr_close_button">Кнопка закриття</string> <string name="smp_servers_preset_address">Попередньо встановлена адреса сервера</string> <string name="chat_is_stopped_indication">Чат зупинено</string> - <string name="save_and_update_group_profile">Збереження та оновлення профілю групи</string> + <string name="save_and_update_group_profile">Зберегти та оновити профіль групи</string> <string name="theme">Тема</string> - <string name="v4_6_audio_video_calls_descr">Підтримка Bluetooth та інші покращення.</string> - <string name="v4_6_group_moderation">Модерація груп</string> + <string name="v4_6_audio_video_calls_descr">Підтримка Bluetooth та інші поліпшення.</string> + <string name="v4_6_group_moderation">Модерація групи</string> <string name="profile_password">Пароль профілю</string> - <string name="video_will_be_received_when_contact_completes_uploading">Відео буде отримано, коли ваш контакт завершить завантаження.</string> - <string name="video_will_be_received_when_contact_is_online">Відео буде отримано, коли ваш контакт буде онлайн, будь ласка, зачекайте або перевірте пізніше!</string> - <string name="file_will_be_received_when_contact_completes_uploading">Файл буде отримано, коли ваш контакт завершить завантаження.</string> + <string name="video_will_be_received_when_contact_completes_uploading">Відео буде отримано, коли ваш контакт завершить його вивантаження.</string> + <string name="video_will_be_received_when_contact_is_online">Відео буде отримано, коли ваш контакт буде в мережі, будь ласка, зачекайте або перевірте пізніше!</string> + <string name="file_will_be_received_when_contact_completes_uploading">Файл буде отримано, коли ваш контакт завершить його вивантаження.</string> <string name="error_saving_file">Помилка збереження файлу</string> <string name="button_delete_contact">Видалити контакт</string> <string name="text_field_set_contact_placeholder">Встановити ім\'я контакту…</string> <string name="choose_file">Файл</string> <string name="from_gallery_button">З галереї</string> - <string name="icon_descr_simplex_team">SimpleX Команда</string> - <string name="contact_wants_to_connect_with_you">хоче зв\'язатися з вами!</string> - <string name="settings_section_title_experimenta">ЕКСПЕРИМЕНТАЛЬНИЙ</string> - <string name="you_must_use_the_most_recent_version_of_database">Ви повинні використовувати найновішу версію вашої бази даних чату ЛИШЕ на одному пристрої, інакше ви можете перестати отримувати повідомлення від деяких контактів.</string> - <string name="messages_section_description">Це налаштування застосовується до повідомлень у вашому поточному профілі чату</string> + <string name="icon_descr_simplex_team">Команда SimpleX</string> + <string name="contact_wants_to_connect_with_you">хоче підключитися до вас!</string> + <string name="settings_section_title_experimenta">ЕКСПЕРИМЕНТАЛЬНІ ФУНКЦІЇ</string> + <string name="you_must_use_the_most_recent_version_of_database">Ви повинні використовувати найновішу версію бази даних чату лише на одному пристрої, інакше ви можете припинити отримання повідомлень від деяких контактів.</string> + <string name="messages_section_description">Цей параметр застосовується до повідомлень у вашому поточному профілі чату</string> <string name="encrypted_database">Зашифрована база даних</string> <string name="error_with_info">Помилка: %s</string> - <string name="database_downgrade">Пониження бази даних</string> - <string name="alert_message_group_invitation_expired">Групове запрошення більше не дійсне, воно було видалено відправником.</string> - <string name="rcv_group_event_member_deleted">видалено %1$s</string> - <string name="group_member_status_intro_invitation">підключення (вступне запрошення)</string> + <string name="database_downgrade">Зниження версії бази даних</string> + <string name="alert_message_group_invitation_expired">Запрошення в групу більше не дійсне, його видалив відправник.</string> + <string name="rcv_group_event_member_deleted">видалив(ла) %1$s</string> + <string name="group_member_status_intro_invitation">підключення (запрошення для введення)</string> <string name="group_member_status_connecting">підключення</string> <string name="no_contacts_to_add">Немає контактів для додавання</string> <string name="initial_member_role">Початкова роль</string> - <string name="clear_contacts_selection_button">Чисто</string> + <string name="clear_contacts_selection_button">Очистити</string> <string name="whats_new_read_more">Читати далі</string> - <string name="v4_3_irreversible_message_deletion">Безповоротне видалення повідомлення</string> - <string name="v4_4_french_interface_descr">Дякуємо користувачам - зробіть свій внесок через Weblate!</string> - <string name="enter_passphrase_notification_desc">Щоб отримувати повідомлення, будь ласка, введіть пароль до бази даних</string> + <string name="v4_3_irreversible_message_deletion">Незворотне видалення повідомлень</string> + <string name="v4_4_french_interface_descr">Дякуємо користувачам – приєднуйтеся через Weblate!</string> + <string name="enter_passphrase_notification_desc">Для отримання сповіщень, будь ласка, введіть пароль бази даних</string> <string name="file_not_found">Файл не знайдено</string> - <string name="connect_via_link">Підключіться за посиланням</string> - <string name="connect_button">Підключіться</string> - <string name="to_reveal_profile_enter_password">Щоб відкрити свій прихований профіль, введіть повний пароль у поле пошуку на сторінці \"Ваші профілі чату\".</string> - <string name="confirm_password">Підтвердьте пароль</string> + <string name="connect_via_link">Підключитися через посилання</string> + <string name="connect_button">Підключитися</string> + <string name="to_reveal_profile_enter_password">Щоб показати ваш схований профіль, введіть повний пароль у поле пошуку на сторінці Ваші профілі чату.</string> + <string name="confirm_password">Підтвердити пароль</string> <string name="ttl_d">%dd</string> - <string name="v4_6_hidden_chat_profiles_descr">Захистіть свої профілі чату паролем!</string> - <string name="decryption_error">Помилка розшифровки</string> + <string name="v4_6_hidden_chat_profiles_descr">Захистіть свої чат-профілі паролем!</string> + <string name="decryption_error">Помилка дешифрування</string> <string name="error_xftp_test_server_auth">Сервер вимагає авторизації для завантаження, перевірте пароль</string> <string name="smp_server_test_upload_file">Завантажити файл</string> <string name="smp_server_test_download_file">Завантажити файл</string> <string name="database_initialization_error_title">Не вдається ініціалізувати базу даних</string> <string name="database_initialization_error_desc">База даних працює некоректно. Натисніть, щоб дізнатися більше</string> - <string name="periodic_notifications_desc">Додаток періодично отримує нові повідомлення - він використовує кілька відсотків заряду акумулятора на день. Додаток не використовує push-сповіщення - дані з вашого пристрою не надсилаються на сервери.</string> - <string name="ntf_channel_calls">Дзвінки SimpleX Chat</string> + <string name="periodic_notifications_desc">Програма періодично отримує нові повідомлення — це використовує кілька відсотків батареї щодня. Програма не використовує торкання сповіщень — дані з вашого пристрою не відправляються на сервери.</string> + <string name="ntf_channel_calls">Дзвінки чату SimpleX</string> <string name="settings_notifications_mode_title">Служба сповіщень</string> <string name="settings_notification_preview_mode_title">Показати попередній перегляд</string> <string name="settings_notification_preview_title">Попередній перегляд сповіщень</string> - <string name="notifications_mode_off">Запускається, коли програма відкрита</string> - <string name="notifications_mode_periodic">Періодично запускається</string> + <string name="notifications_mode_off">Запускається, коли додаток відкритий</string> + <string name="notifications_mode_periodic">Запускається періодично</string> <string name="notification_preview_mode_message">Текст повідомлення</string> - <string name="notification_preview_mode_contact">Ім\'я контактної особи</string> - <string name="auth_confirm_credential">Підтвердіть свій обліковий запис</string> - <string name="you_can_turn_on_lock">Увімкнути SimpleX Lock можна в Налаштуваннях.</string> - <string name="message_delivery_error_desc">Швидше за все, цей контакт видалив зв\'язок з вами.</string> - <string name="icon_descr_context">Контекстна піктограма</string> + <string name="notification_preview_mode_contact">Ім\'я контакту</string> + <string name="auth_confirm_credential">Підтвердіть свої облікові дані</string> + <string name="you_can_turn_on_lock">Ви можете увімкнути блокування SimpleX через налаштування.</string> + <string name="message_delivery_error_desc">Ймовірно, цей контакт видалив з вами зв\'язок.</string> + <string name="icon_descr_context">Значок контексту</string> <string name="images_limit_title">Забагато зображень!</string> <string name="videos_limit_title">Забагато відео!</string> <string name="you_are_observer">ви спостерігач</string> - <string name="colored_text">кольорові</string> - <string name="callstatus_ended">дзвінок закінчився %1$s</string> - <string name="callstatus_error">помилка виклику</string> - <string name="next_generation_of_private_messaging">Наступне покоління приватних повідомлень</string> - <string name="opensource_protocol_and_code_anybody_can_run_servers">Протокол і код з відкритим вихідним кодом - будь-хто може запускати сервери.</string> - <string name="settings_developer_tools">Інструменти для розробників</string> - <string name="settings_experimental_features">Експериментальні особливості</string> + <string name="colored_text">кольоровий</string> + <string name="callstatus_ended">дзвінок завершено %1$s</string> + <string name="callstatus_error">помилка дзвінка</string> + <string name="next_generation_of_private_messaging">Наступне покоління приватного обміну повідомленнями</string> + <string name="opensource_protocol_and_code_anybody_can_run_servers">Відкритий протокол та код – кожен може запустити сервери.</string> + <string name="settings_developer_tools">Інструменти розробника</string> + <string name="settings_experimental_features">Експериментальні функції</string> <string name="settings_section_title_calls">ДЗВІНКИ</string> - <string name="save_passphrase_in_keychain">Збережіть парольну фразу у сховищі ключів</string> + <string name="save_passphrase_in_keychain">Зберегти ключову фразу в сховищі ключів</string> <string name="error_encrypting_database">Помилка шифрування бази даних</string> - <string name="remove_passphrase_from_keychain">Видалити парольну фразу з Keystore\?</string> - <string name="enter_correct_current_passphrase">Будь ласка, введіть правильний поточний пароль.</string> - <string name="store_passphrase_securely_without_recover">Будь ласка, зберігайте пароль надійно, ви НЕ зможете отримати доступ до чату, якщо втратите його.</string> + <string name="remove_passphrase_from_keychain">Вилучити ключову фразу із сховища ключів?</string> + <string name="enter_correct_current_passphrase">Будь ласка, введіть правильну поточну ключову фразу.</string> + <string name="store_passphrase_securely_without_recover">Будь ласка, зберігайте ключову фразу надійно, ви НЕ зможете отримати доступ до чату, якщо втратите її.</string> <string name="users_delete_question">Видалити профіль чату\?</string> - <string name="stop_file__action">Зупинити файл</string> - <string name="stop_snd_file__title">Припинити надсилати файл\?</string> + <string name="stop_file__action">Зупинити відправлення файлу</string> + <string name="stop_snd_file__title">Зупинити відправлення файлу?</string> <string name="create_group">Створити секретну групу</string> <string name="to_share_with_your_contact">(щоб поділитися з вашим контактом)</string> - <string name="connect_via_link_or_qr_from_clipboard_or_in_person">(відсканувати або вставити з буфера обміну)</string> - <string name="you_can_connect_to_simplex_chat_founder"><![CDATA[Ви можете <font color="#0088ff"> зв\'язатися з розробниками SimpleX Chat, щоб задати будь-які питання та отримати оновлення</font>.]]></string> - <string name="desktop_scan_QR_code_from_app_via_scan_QR_code"><![CDATA[💻 десктоп: відскануйте відображений QR-код з додатку, за допомогою <b>Відскануйте QR-код</b>.]]></string> - <string name="icon_descr_address">SimpleX Адреса</string> + <string name="connect_via_link_or_qr_from_clipboard_or_in_person">(сканувати або вставити з буферу обміну)</string> + <string name="you_can_connect_to_simplex_chat_founder"><![CDATA[Ви можете <font color="#0088ff">підключитися до розробників SimpleX Chat, щоб задати будь-які питання і отримувати оновлення</font>.]]></string> + <string name="desktop_scan_QR_code_from_app_via_scan_QR_code"><![CDATA[💻 настільний комп\'ютер: скануйте відображений QR-код з додатка за допомогою <b>Сканувати QR-код</b>.]]></string> + <string name="icon_descr_address">Адреса SimpleX</string> <string name="show_QR_code">Показати QR-код</string> <string name="joining_group">Приєднання до групи</string> <string name="italic_text">курсив</string> - <string name="webrtc_ice_servers">Сервери WebRTC ICE</string> - <string name="allow_accepting_calls_from_lock_screen">Увімкніть дзвінки з екрана блокування через Налаштування.</string> - <string name="v5_0_large_files_support_descr">Швидко і без очікування, поки відправник буде онлайн!</string> + <string name="webrtc_ice_servers">WebRTC сервери ICE</string> + <string name="allow_accepting_calls_from_lock_screen">Увімкніть прийом викликів з екрану блокування через Налаштування.</string> + <string name="v5_0_large_files_support_descr">Швидко та без очікування, поки відправник у мережі!</string> <string name="item_info_no_text">немає тексту</string> - <string name="button_send_direct_message">Надішліть пряме повідомлення</string> + <string name="button_send_direct_message">Надіслати пряме повідомлення</string> <string name="network_option_ping_interval">Інтервал PING</string> <string name="network_option_ping_count">Кількість PING</string> <string name="network_option_enable_tcp_keep_alive">Увімкнути TCP keep-alive</string> <string name="users_delete_profile_for">Видалити профіль чату для</string> <string name="user_hide">Приховати</string> - <string name="theme_dark">Темний</string> - <string name="language_system">Система</string> + <string name="theme_dark">Темна</string> + <string name="language_system">Системна</string> <string name="dark_theme">Темна тема</string> - <string name="import_theme">Імпорт теми</string> - <string name="export_theme">Експорт теми</string> + <string name="import_theme">Імпортувати тему</string> + <string name="export_theme">Експортувати тему</string> <string name="import_theme_error_desc">Переконайтеся, що файл має правильний синтаксис YAML. Експортуйте тему, щоб мати приклад структури файлу теми.</string> <string name="reset_color">Скинути кольори</string> <string name="chat_preferences_default">за замовчуванням (%s)</string> - <string name="only_you_can_make_calls">Дзвонити можете тільки ви.</string> + <string name="only_you_can_make_calls">Тільки ви можете здійснювати дзвінки.</string> <string name="only_your_contact_can_make_calls">Тільки ваш контакт може здійснювати дзвінки.</string> <string name="whats_new">Що нового</string> <string name="v4_3_voice_messages">Голосові повідомлення</string> - <string name="v4_5_transport_isolation_descr">За профілем чату (за замовчуванням) або за з\'єднанням (BETA).</string> - <string name="v5_1_custom_themes">Користувацькі теми</string> + <string name="v4_5_transport_isolation_descr">За профілем чату (типово) або за підключенням (BETA).</string> + <string name="v5_1_custom_themes">Власні теми</string> <string name="v5_1_better_messages_descr">- голосові повідомлення до 5 хвилин. -\n- користувальницький час зникнення. +\n- власний час на зникнення. \n- історія редагування.</string> <string name="v5_1_japanese_portuguese_interface">Японський та португальський інтерфейс</string> <string name="group_invitation_tap_to_join">Натисніть, щоб приєднатися</string> - <string name="group_invitation_tap_to_join_incognito">Натисніть, щоб приєднатися інкогніто</string> - <string name="you_rejected_group_invitation">Ви відхилили запрошення до групи</string> - <string name="rcv_group_event_user_deleted">видалив вас</string> + <string name="group_invitation_tap_to_join_incognito">Натисніть, щоб приєднатися анонімно</string> + <string name="you_rejected_group_invitation">Ви відхилили запрошення в групу</string> + <string name="rcv_group_event_user_deleted">вас видалили</string> <string name="group_member_role_owner">власник</string> <string name="group_member_status_removed">видалено</string> - <string name="if_you_cannot_meet_in_person_scan_QR_in_video_call_or_ask_for_invitation_link"><![CDATA[Якщо ви не можете зустрітися особисто, ви можете <b>відсканувати QR-код у відеодзвінку</b>, або ваш контакт може поділитися посиланням на запрошення.]]></string> - <string name="how_to_use_simplex_chat">Як ним користуватися</string> + <string name="if_you_cannot_meet_in_person_scan_QR_in_video_call_or_ask_for_invitation_link"><![CDATA[Якщо ви не можете зустрітися особисто, ви можете <b>сканувати QR-код у відеовиклику</b>, або ваш контакт може поділитися посиланням на запрошення.]]></string> + <string name="how_to_use_simplex_chat">Як користуватися</string> <string name="network_session_mode_entity">Підключення</string> - <string name="disable_onion_hosts_when_not_supported"><![CDATA[Встановіть <i>Використовувати .onion хости</i> на Ні, якщо SOCKS проксі не підтримує їх.]]></string> - <string name="show_dev_options">Покажи:</string> - <string name="hide_dev_options">Приховати:</string> - <string name="non_fatal_errors_occured_during_import">Під час імпорту виникли деякі нефатальні помилки – ви можете переглянути консоль чату, щоб дізнатися більше.</string> - <string name="enable_automatic_deletion_message">Цю дію неможливо скасувати - повідомлення, надіслані та отримані раніше, ніж вибрані, будуть видалені. Це може зайняти кілька хвилин.</string> - <string name="you_have_to_enter_passphrase_every_time">Вам доведеться вводити парольну фразу щоразу при запуску програми - вона не зберігається на пристрої.</string> - <string name="change_database_passphrase_question">Змінити пароль до бази даних\?</string> - <string name="cannot_access_keychain">Не вдається отримати доступ до сховища ключів, щоб зберегти пароль до бази даних</string> - <string name="save_passphrase_and_open_chat">Збережіть пароль і відкрийте чат</string> - <string name="restore_passphrase_not_found_desc">Пароль не знайдено у сховищі ключів, будь ласка, введіть його вручну. Це могло статися, якщо ви відновили дані програми за допомогою інструменту резервного копіювання. Якщо це не так, зверніться до розробників.</string> + <string name="disable_onion_hosts_when_not_supported"><![CDATA[Встановіть <i>Використовувати .onion-хости</i> на Ні, якщо SOCKS-проксі їх не підтримує.]]></string> + <string name="show_dev_options">Показати:</string> + <string name="hide_dev_options">Сховати:</string> + <string name="non_fatal_errors_occured_during_import">Під час імпорту сталися деякі невідновні помилки - ви можете переглянути консоль чату для отримання більше деталей.</string> + <string name="enable_automatic_deletion_message">Цю дію неможливо відмінити - будуть видалені повідомлення, відправлені та отримані раніше вибраного часу. Це може зайняти декілька хвилин.</string> + <string name="you_have_to_enter_passphrase_every_time">Вам потрібно вводити ключову фразу кожен раз при запуску додатка - вона не зберігається на пристрої.</string> + <string name="change_database_passphrase_question">Змінити ключову фразу бази даних?</string> + <string name="cannot_access_keychain">Не вдається отримати доступ до сховища ключів для збереження пароля бази даних</string> + <string name="save_passphrase_and_open_chat">Зберегти ключову фразу і відкрити чат</string> + <string name="restore_passphrase_not_found_desc">Ключова фраза не знайдена в сховищі ключів, будь ласка, введіть її вручну. Це може трапитися, якщо ви відновили дані додатка за допомогою інструменту резервного копіювання. Якщо це не так, зверніться до розробників.</string> <string name="delete_chat_profile">Видалити профіль чату</string> <string name="ttl_sec">%d сек</string> <string name="search_verb">Пошук</string> - <string name="la_mode_off">Вимкнено</string> - <string name="receipts_contacts_override_disabled">Відправлення підтвердження доставлення вимкнено для контакту %d</string> - <string name="receipts_contacts_disable_keep_overrides">Вимкнути (зберегти перевизначення)</string> + <string name="la_mode_off">Вимк.</string> + <string name="receipts_contacts_override_disabled">Надсилання повідомлень про доставку вимкнено для %d контактів</string> + <string name="receipts_contacts_disable_keep_overrides">Вимкнути (зберегти заміни)</string> <string name="receipts_contacts_enable_for_all">Увімкнути для всіх</string> - <string name="conn_event_ratchet_sync_ok">шифрування ok</string> + <string name="conn_event_ratchet_sync_ok">шифрування в порядку</string> <string name="conn_event_ratchet_sync_started">узгодження шифрування…</string> <string name="snd_conn_event_ratchet_sync_started">узгодження шифрування для %s…</string> - <string name="sender_at_ts">%s в %s</string> - <string name="sending_delivery_receipts_will_be_enabled">Для всіх контактів буде ввімкнено відправку підтвердження доставки.</string> - <string name="sending_delivery_receipts_will_be_enabled_all_profiles">Відправлення підтвердження доставлення буде ввімкнено для всіх контактів у всіх видимих профілях чату.</string> - <string name="you_can_enable_delivery_receipts_later">Ви можете увімкнути пізніше в Налаштуваннях</string> - <string name="dont_enable_receipts">Не вмикати</string> - <string name="error_enabling_delivery_receipts">Помилка активації підтвердження доставлення!</string> - <string name="error_aborting_address_change">Помилка переривання зміни адреси</string> - <string name="abort_switch_receiving_address">Скасувати зміну адреси</string> - <string name="allow_to_send_files">Дозволяє надсилати файли та медіа.</string> - <string name="files_are_prohibited_in_group">Файли та медіа в цій групі заборонені.</string> - <string name="connect_via_link_incognito">Підключайтеся інкогніто</string> + <string name="sender_at_ts">%s о %s</string> + <string name="sending_delivery_receipts_will_be_enabled">Відправка квитанцій про доставку буде увімкнена для всіх контактів.</string> + <string name="sending_delivery_receipts_will_be_enabled_all_profiles">Відправка квитанцій про доставку буде увімкнена для всіх контактів у всіх видимих чат-профілях.</string> + <string name="you_can_enable_delivery_receipts_later">Ви можете увімкнути їх пізніше через налаштування</string> + <string name="dont_enable_receipts">Не увімкнювати</string> + <string name="error_enabling_delivery_receipts">Помилка увімкнення квитанцій про доставку!</string> + <string name="error_aborting_address_change">Помилка відміни зміни адреси</string> + <string name="abort_switch_receiving_address">Перервати зміну адреси</string> + <string name="allow_to_send_files">Дозволити надсилання файлів та медіафайлів.</string> + <string name="files_are_prohibited_in_group">Файли та медіафайли заборонені в цій групі.</string> + <string name="connect_via_link_incognito">Підключити інкогніто</string> <string name="connect_use_current_profile">Використовувати поточний профіль</string> - <string name="turn_off_battery_optimization_button">Дозвольте</string> + <string name="turn_off_battery_optimization_button">Дозволити</string> <string name="disable_notifications_button">Вимкнути сповіщення</string> - <string name="turn_off_system_restriction_button">Відкрийте налаштування програми</string> - <string name="system_restricted_background_desc">SimpleX не може працювати у фоновому режимі. Ви будете отримувати сповіщення лише під час роботи програми.</string> - <string name="system_restricted_background_in_call_title">Ніяких фонових дзвінків</string> - <string name="system_restricted_background_in_call_desc">Додаток можна закрити після 1 хвилини роботи у фоновому режимі.</string> + <string name="turn_off_system_restriction_button">Відкрити налаштування додатка</string> + <string name="system_restricted_background_desc">SimpleX не може працювати в фоновому режимі. Ви отримуватимете сповіщення лише тоді, коли програма працює.</string> + <string name="system_restricted_background_in_call_title">Обмеженість фонових дзвінків</string> + <string name="system_restricted_background_in_call_desc">Додаток може бути закритий після 1 хвилини в фоновому режимі.</string> <string name="in_reply_to">У відповідь на</string> <string name="no_history">Немає історії</string> - <string name="files_and_media_prohibited">Файли та медіа заборонені!</string> - <string name="connect__your_profile_will_be_shared">Ваш профіль %1$s буде опублікований.</string> + <string name="files_and_media_prohibited">Заборонено файли та медіа!</string> + <string name="connect__your_profile_will_be_shared">Буде відправлено ваш профіль %1$s.</string> <string name="receipts_groups_disable_for_all">Вимкнути для всіх груп</string> - <string name="settings_section_title_delivery_receipts">НАДІШЛІТЬ ПІДТВЕРДЖЕННЯ ДОСТАВКИ НА АДРЕСУ</string> - <string name="connect_via_member_address_alert_title">Підключатися напряму\?</string> + <string name="settings_section_title_delivery_receipts">НАДСИЛАТИ ПОВІДОМЛЕННЯ ПРО ДОСТАВКУ</string> + <string name="connect_via_member_address_alert_title">Підключитися безпосередньо?</string> <string name="recipient_colon_delivery_status">%s: %s</string> - <string name="connect_via_member_address_alert_desc">Запит на підключення буде надіслано цьому учаснику групи.</string> - <string name="fix_connection_confirm">Виправлення</string> + <string name="connect_via_member_address_alert_desc">Запит на підключення буде відправлено учаснику групи.</string> + <string name="fix_connection_confirm">Виправити</string> <string name="files_and_media">Файли та медіа</string> <string name="v5_2_favourites_filter_descr">Фільтруйте непрочитані та улюблені чати.</string> <string name="v5_2_favourites_filter">Швидше знаходьте чати</string> - <string name="v5_2_disappear_one_message">Зробити так, щоб одне повідомлення зникло</string> - <string name="no_selected_chat">Немає вибраного чату</string> + <string name="v5_2_disappear_one_message">Зникайте одне повідомлення</string> + <string name="no_selected_chat">Не обрано жодного чату</string> <string name="abort_switch_receiving_address_confirm">Скасувати</string> <string name="choose_file_title">Виберіть файл</string> <string name="receipts_section_contacts">Контакти</string> <string name="receipts_section_description">Ці налаштування стосуються вашого поточного профілю</string> - <string name="receipts_contacts_title_disable">Вимкнути підтвердження\?</string> - <string name="receipts_contacts_title_enable">Активувати підтвердження\?</string> - <string name="conn_event_ratchet_sync_allowed">переузгодження шифрування дозволено</string> - <string name="snd_conn_event_ratchet_sync_agreed">узгоджене шифрування для %s</string> - <string name="snd_conn_event_ratchet_sync_allowed">переузгодження шифрування дозволено для %s</string> - <string name="snd_conn_event_ratchet_sync_required">потрібно переузгодження шифрування для %s</string> - <string name="rcv_conn_event_verification_code_reset">змінено код безпеки</string> + <string name="receipts_contacts_title_disable">Вимкнути повідомлення про доставку?</string> + <string name="receipts_contacts_title_enable">Увімкнути повідомлення про доставку?</string> + <string name="conn_event_ratchet_sync_allowed">можлива перезапис шифрування</string> + <string name="snd_conn_event_ratchet_sync_agreed">шифрування узгоджено для %s</string> + <string name="snd_conn_event_ratchet_sync_allowed">можлива перезапис шифрування для %s</string> + <string name="snd_conn_event_ratchet_sync_required">перезапис шифрування обов\'язковий для %s</string> + <string name="rcv_conn_event_verification_code_reset">код безпеки змінено</string> <string name="fix_connection_not_supported_by_contact">Виправлення не підтримується контактом</string> - <string name="send_receipts">Надсилати звіти про доставку</string> - <string name="prohibit_sending_files">Заборонити надсилання файлів і медіа.</string> - <string name="v5_2_fix_encryption_descr">Виправити шифрування після відновлення резервних копій.</string> - <string name="v5_2_fix_encryption">Зберігайте свої зв\'язки</string> - <string name="v5_2_more_things_descr">- стабільніше доставлення повідомлень. -\n- трохи кращі групи. -\n- і багато іншого!</string> - <string name="in_developing_title">Вже скоро!</string> + <string name="send_receipts">Надсилати звіти</string> + <string name="prohibit_sending_files">Заборонити надсилання файлів та медіафайлів.</string> + <string name="v5_2_fix_encryption_descr">Виправте шифрування після відновлення резервних копій.</string> + <string name="v5_2_fix_encryption">Зберігайте ваші підключення</string> + <string name="v5_2_more_things_descr">- стабільніша доставка повідомлень. +\n- трошки кращі групи. +\n- та багато іншого!</string> + <string name="in_developing_title">Скоро!</string> <string name="delivery">Доставка</string> - <string name="no_info_on_delivery">Немає інформації про доставлення</string> + <string name="no_info_on_delivery">Немає інформації про доставку</string> <string name="no_filtered_chats">Немає фільтрованих чатів</string> - <string name="sync_connection_force_confirm">Переузгодьте</string> - <string name="unfavorite_chat">Неулюблене</string> + <string name="sync_connection_force_confirm">Узгодити повторно</string> + <string name="unfavorite_chat">Забрати з улюблених</string> <string name="receipts_contacts_disable_for_all">Вимкнути для всіх</string> - <string name="receipts_contacts_enable_keep_overrides">Увімкнути (зберегти перевизначення)</string> - <string name="receipts_contacts_override_enabled">Підтвердження надсилання ввімкнено для контакту %d</string> - <string name="receipts_section_groups">Невеликі групи (максимум 20 осіб)</string> - <string name="receipts_groups_title_disable">Вимкнути підтвердження доставлення для груп\?</string> - <string name="receipts_groups_title_enable">Активувати підтвердження доставлення для груп\?</string> - <string name="receipts_groups_override_enabled">Надсилання підтвердження доставлення дозволено для груп %d</string> - <string name="receipts_groups_disable_keep_overrides">Вимкнути (зберегти групові перевизначення)</string> + <string name="receipts_contacts_enable_keep_overrides">Увімкнути (зберегти заміни)</string> + <string name="receipts_contacts_override_enabled">Надсилання повідомлень про доставку увімкнено для %d контактів</string> + <string name="receipts_section_groups">Невеликі групи (макс. 20)</string> + <string name="receipts_groups_title_disable">Вимкнути повідомлення про доставку для груп?</string> + <string name="receipts_groups_title_enable">Увімкнути повідомлення про доставку для груп?</string> + <string name="receipts_groups_override_enabled">Надсилання повідомлень про доставку увімкнено для %d груп</string> + <string name="receipts_groups_disable_keep_overrides">Вимкнути (зберегти заміни для груп)</string> <string name="receipts_groups_enable_for_all">Увімкнути для всіх груп</string> - <string name="receipts_groups_enable_keep_overrides">Увімкнути (зберегти перевизначення групи)</string> - <string name="conn_event_ratchet_sync_required">потрібне повторне узгодження шифрування</string> - <string name="send_receipts_disabled_alert_title">Підтвердження доставки вимкнено</string> + <string name="receipts_groups_enable_keep_overrides">Увімкнути (зберегти заміни для груп)</string> + <string name="conn_event_ratchet_sync_required">перезапис шифрування обов\'язковий</string> + <string name="send_receipts_disabled_alert_title">Звіти вимкнено</string> <string name="send_receipts_disabled">вимкнено</string> - <string name="send_receipts_disabled_alert_msg">У цій групі більше %1$d учасників, підтвердження доставлення не буде надіслано.</string> - <string name="in_developing_desc">Ця функція поки що не підтримується. Спробуйте наступну версію.</string> - <string name="fix_connection">Виправити з\'єднання</string> - <string name="fix_connection_question">Виправити з\'єднання\?</string> - <string name="renegotiate_encryption">Переузгодьте шифрування</string> - <string name="network_option_protocol_timeout_per_kb">Тайм-аут протоколу на КБ</string> - <string name="conn_event_ratchet_sync_agreed">узгоджено шифрування</string> - <string name="rcv_group_event_2_members_connected">%s і %s під\'єднано</string> + <string name="send_receipts_disabled_alert_msg">У цій групі понад %1$d учасників, звіти про доставку не відправляються.</string> + <string name="in_developing_desc">Ця функція ще не підтримується. Спробуйте наступний випуск.</string> + <string name="fix_connection">Виправити підключення</string> + <string name="fix_connection_question">Виправити підключення?</string> + <string name="renegotiate_encryption">Переговорити щодо шифрування</string> + <string name="network_option_protocol_timeout_per_kb">Тайм-аут протоколу за КБ</string> + <string name="conn_event_ratchet_sync_agreed">шифрування узгоджено</string> + <string name="rcv_group_event_2_members_connected">%s і %s підключилися</string> <string name="fix_connection_not_supported_by_group_member">Виправлення не підтримується учасником групи</string> - <string name="v5_2_message_delivery_receipts">Підтвердження доставлення повідомлення!</string> - <string name="v5_2_message_delivery_receipts_descr">Другу галочку ми пропустили! ✅</string> - <string name="favorite_chat">Улюблений</string> - <string name="v5_2_more_things">Ще кілька моментів</string> - <string name="connect__a_new_random_profile_will_be_shared">Буде створено новий випадковий профіль.</string> - <string name="delivery_receipts_title">Підтвердження доставлення!</string> - <string name="delivery_receipts_are_disabled">Підтвердження доставлення вимкнено!</string> + <string name="v5_2_message_delivery_receipts">Підтвердження доставки повідомлень!</string> + <string name="v5_2_message_delivery_receipts_descr">Друга галочка, яку ми пропустили! ✅</string> + <string name="favorite_chat">Улюблені</string> + <string name="v5_2_more_things">Ще кілька речей</string> + <string name="connect__a_new_random_profile_will_be_shared">Буде відправлено новий випадковий профіль.</string> + <string name="delivery_receipts_title">Квитанції про доставку!</string> + <string name="delivery_receipts_are_disabled">Квитанції про доставку вимкнено!</string> <string name="enable_receipts_all">Увімкнути</string> - <string name="snd_conn_event_ratchet_sync_ok">шифрування ok для %s</string> - <string name="v5_2_disappear_one_message_descr">Навіть коли вимкнений у розмові.</string> - <string name="privacy_message_draft">Чернетка повідомлення</string> - <string name="only_owners_can_enable_files_and_media">Тільки власники груп можуть вмикати файли та медіа.</string> - <string name="paste_the_link_you_received_to_connect_with_your_contact">Вставте отримане посилання для зв\'язку з вашим контактом…</string> - <string name="receipts_groups_override_disabled">Відправлення підтвердження доставки вимкнено для груп %d</string> - <string name="rcv_group_event_3_members_connected">%s, %s і %s підключено</string> - <string name="receipts_section_description_1">Їх можна перевизначити в налаштуваннях контактів і груп.</string> - <string name="system_restricted_background_warn"><![CDATA[Щоб увімкнути сповіщення, виберіть <b>Використання акумулятора програми</b> / <b>Необмежено</b> в налаштуваннях програми.]]></string> - <string name="system_restricted_background_in_call_warn"><![CDATA[Щоб здійснювати дзвінки у фоновому режимі, виберіть <b>Використання акумулятора програми</b> / <b>Без обмежень</b> у налаштуваннях програми.]]></string> - <string name="connect_use_new_incognito_profile">Використовуйте новий профіль інкогніто</string> - <string name="you_can_enable_delivery_receipts_later_alert">Ви можете увімкнути їх пізніше в налаштуваннях конфіденційності та безпеки програми.</string> - <string name="rcv_group_event_n_members_connected">%s, %s та %d інших учасників під\'єднано</string> - <string name="privacy_show_last_messages">Показати останні повідомлення</string> + <string name="snd_conn_event_ratchet_sync_ok">шифрування в порядку для %s</string> + <string name="v5_2_disappear_one_message_descr">Навіть коли вимкнено в розмові.</string> + <string name="privacy_message_draft">Чорновик повідомлення</string> + <string name="only_owners_can_enable_files_and_media">Тільки власники групи можуть включити файли та медіа.</string> + <string name="paste_the_link_you_received_to_connect_with_your_contact">Вставте посилання, яке ви отримали, щоб підключитися до свого контакту…</string> + <string name="receipts_groups_override_disabled">Надсилання повідомлень про доставку вимкнено для %d груп</string> + <string name="rcv_group_event_3_members_connected">%s, %s і %s підключилися</string> + <string name="receipts_section_description_1">Їх можна замінити в налаштуваннях контактів і груп.</string> + <string name="system_restricted_background_warn"><![CDATA[Щоб увімкнути сповіщення, оберіть, будь ласка, <b>Використання батареї додатком</b> / <b>Без обмежень</b> у налаштуваннях додатка.]]></string> + <string name="system_restricted_background_in_call_warn"><![CDATA[Щоб здійснювати дзвінки в фоновому режимі, будь ласка, оберіть <b>Використання батареї додатком</b> / <b>Без обмежень</b> у налаштуваннях додатка.]]></string> + <string name="connect_use_new_incognito_profile">Використовувати новий інкогніто-профіль</string> + <string name="you_can_enable_delivery_receipts_later_alert">Ви зможете увімкнути їх пізніше через налаштування конфіденційності та безпеки додатка.</string> + <string name="rcv_group_event_n_members_connected">%s, %s і ще %d учасників підключилися</string> + <string name="privacy_show_last_messages">Показувати останні повідомлення</string> <string name="error_synchronizing_connection">Помилка синхронізації з\'єднання</string> - <string name="abort_switch_receiving_address_question">Скасувати зміну адреси\?</string> - <string name="abort_switch_receiving_address_desc">Зміна адреси буде скасована. Буде використано стару адресу отримання.</string> - <string name="sync_connection_force_question">Переузгодьте шифрування\?</string> - <string name="sync_connection_force_desc">Шифрування працює і нова угода про шифрування не потрібна. Це може призвести до помилок з\'єднання!</string> - <string name="group_members_can_send_files">Учасники групи можуть надсилати файли та медіа.</string> - <string name="database_will_be_encrypted_and_passphrase_stored_in_settings">База даних буде зашифрована, а ключова фраза збережена в налаштуваннях.</string> + <string name="abort_switch_receiving_address_question">Скасувати зміну адреси для отримання?</string> + <string name="abort_switch_receiving_address_desc">Зміна адреси буде скасована. Буде використовуватися стара адреса для отримання.</string> + <string name="sync_connection_force_question">Повторно узгодити шифрування?</string> + <string name="sync_connection_force_desc">Шифрування працює і нова угода про шифрування не потрібна. Це може призвести до помилок підключення!</string> + <string name="group_members_can_send_files">Учасники групи можуть надсилати файли та медіафайли.</string> + <string name="database_will_be_encrypted_and_passphrase_stored_in_settings">База даних буде зашифрована, і ключова фраза буде збережена в налаштуваннях.</string> <string name="expand_verb">Розгорнути</string> <string name="connect_plan_repeat_connection_request">Повторити запит на підключення?</string> - <string name="encryption_renegotiation_error">Помилка повторного узгодження шифрування</string> - <string name="rcv_direct_event_contact_deleted">видалений контакт</string> - <string name="connect_plan_you_are_already_connecting_to_vName">Ви вже з\'єднані з %1$s.</string> + <string name="encryption_renegotiation_error">Помилка переговорів щодо шифрування</string> + <string name="rcv_direct_event_contact_deleted">видалено контакт</string> + <string name="connect_plan_you_are_already_connecting_to_vName">Ви вже підключаєтеся до %1$s.</string> <string name="rcv_group_event_open_chat">Відкрити</string> - <string name="v5_3_encrypt_local_files">Шифрування збережених файлів і носіїв</string> + <string name="v5_3_encrypt_local_files">Шифрування збережених файлів та медіа</string> <string name="error_alert_title">Помилка</string> - <string name="error_creating_member_contact">Помилка при створенні контакту користувача</string> - <string name="connect_plan_you_are_already_joining_the_group_via_this_link">Ви вже приєдналися до групи за цим посиланням.</string> + <string name="error_creating_member_contact">Помилка при створенні контакту учасника</string> + <string name="connect_plan_you_are_already_joining_the_group_via_this_link">Ви вже приєднуєтеся до групи за цим посиланням.</string> <string name="create_group_button">Створити групу</string> - <string name="socks_proxy_setting_limitations"><![CDATA[<b>Зверніть увагу</b>: ретранслятори повідомлень і файлів підключаються через проксі SOCKS. Дзвінки та надсилання попередніх переглядів посилань використовують пряме з’єднання.]]></string> + <string name="socks_proxy_setting_limitations"><![CDATA[<b>Зверніть увагу</b>: ретрансляція повідомлень та файлів підключається через SOCKS-проксі. Дзвінки та відправлення переглядів посилань використовують пряме підключення.]]></string> <string name="create_another_profile_button">Створити профіль</string> - <string name="group_members_2">%s та %s</string> - <string name="connect_plan_join_your_group">Приєднатися до групи?</string> - <string name="connect_plan_you_are_already_joining_the_group_vName">Ви вже приєдналися до групи %1$s.</string> - <string name="encrypt_local_files">Шифрування локальних файлів</string> - <string name="connect_plan_this_is_your_own_one_time_link">Це ваше власне одноразове посилання!</string> - <string name="marked_deleted_items_description">%d повідомлень позначено як видалені</string> - <string name="v5_3_new_desktop_app">Новий десктопний застосунок!</string> + <string name="group_members_2">%s і %s</string> + <string name="connect_plan_join_your_group">Приєднатися до вашої групи?</string> + <string name="connect_plan_you_are_already_joining_the_group_vName">Ви вже приєднуєтеся до групи %1$s.</string> + <string name="encrypt_local_files">Шифрувати локальні файли</string> + <string name="connect_plan_this_is_your_own_one_time_link">Це ваш власний одноразовий посилання!</string> + <string name="marked_deleted_items_description">%d повідомлень відзначено як видалені</string> + <string name="v5_3_new_desktop_app">Новий додаток для комп\'ютера!</string> <string name="v5_3_new_interface_languages">6 нових мов інтерфейсу</string> <string name="connect_plan_group_already_exists">Група вже існує!</string> - <string name="v5_3_encrypt_local_files_descr">Застосунок шифрує нові локальні файли (крім відео).</string> - <string name="connect_plan_already_connecting">Вже під\'єднуємося!</string> - <string name="you_can_change_it_later">Випадкова фраза зберігається у налаштуваннях у вигляді відкритого тексту. + <string name="v5_3_encrypt_local_files_descr">Додаток шифрує нові локальні файли (крім відео).</string> + <string name="connect_plan_already_connecting">Вже підключено!</string> + <string name="you_can_change_it_later">Випадковий пароль зберігається в налаштуваннях у відкритому вигляді. \nВи можете змінити його пізніше.</string> - <string name="compose_send_direct_message_to_connect">Надішліть пряме повідомлення, щоб підключитися</string> - <string name="video_decoding_exception_desc">Відео не може бути декодовано. Будь ласка, спробуйте інше відео або зверніться до розробників.</string> - <string name="rcv_group_event_1_member_connected">%s підключено</string> - <string name="rcv_group_and_other_events">ще інших подій - %d</string> - <string name="v5_3_discover_join_groups">Знаходьте та приєднуйтесь до груп</string> - <string name="connect_plan_connect_via_link">Підключитися за посиланням?</string> - <string name="database_encryption_will_be_updated_in_settings">Пароль для шифрування бази даних буде оновлено і збережено в налаштуваннях.</string> - <string name="connect_plan_already_joining_the_group">Вже долучаємось до групи!</string> - <string name="group_members_n">члени %s, %s та %d</string> - <string name="moderated_items_description">%d повідомлень модерує %s</string> - <string name="remove_passphrase_from_settings">Видалити парольну фразу з налаштувань?</string> - <string name="unblock_member_button">Розблокувати</string> - <string name="use_random_passphrase">Використовуйте випадкову парольну фразу</string> + <string name="compose_send_direct_message_to_connect">Відправте приватне повідомлення для підключення</string> + <string name="video_decoding_exception_desc">Неможливо декодувати відео. Спробуйте інше відео або зв\'яжіться з розробниками.</string> + <string name="rcv_group_event_1_member_connected">%s підключився</string> + <string name="rcv_group_and_other_events">і ще %d подій</string> + <string name="v5_3_discover_join_groups">Відкривайте та приєднуйтесь до груп</string> + <string name="connect_plan_connect_via_link">Підключитися за допомогою посилання?</string> + <string name="database_encryption_will_be_updated_in_settings">Ключова фраза шифрування бази даних буде оновлена і збережена в налаштуваннях.</string> + <string name="connect_plan_already_joining_the_group">Вже приєднано до групи!</string> + <string name="group_members_n">%s, %s і %d учасників</string> + <string name="moderated_items_description">%1$d повідомлень модеровано %2$s</string> + <string name="remove_passphrase_from_settings">Вилучити ключову фразу із налаштувань?</string> + <string name="unblock_member_button">Розблокувати учасника</string> + <string name="use_random_passphrase">Використовувати випадковий пароль</string> <string name="connect_plan_connect_to_yourself">Підключитися до себе?</string> - <string name="save_passphrase_in_settings">Зберегти парольну фразу в налаштуваннях</string> + <string name="save_passphrase_in_settings">Зберегти ключову фразу в налаштуваннях</string> <string name="v5_3_simpler_incognito_mode">Спрощений режим інкогніто</string> - <string name="contact_tap_to_connect">Натисніть, щоб підключитися</string> - <string name="setup_database_passphrase">Ключова фраза для налаштування бази даних</string> + <string name="contact_tap_to_connect">Торкніться, щоб підключитися</string> + <string name="setup_database_passphrase">Налаштування паролю бази даних</string> <string name="connect_plan_you_are_already_in_group_vName">Ви вже в групі %1$s.</string> - <string name="connect_plan_this_is_your_own_simplex_address">Це ваша власна SimpleX адреса!</string> - <string name="alert_text_encryption_renegotiation_failed">Повторне узгодження шифрування не вдалося.</string> + <string name="connect_plan_this_is_your_own_simplex_address">Це ваш власний адреса SimpleX!</string> + <string name="alert_text_encryption_renegotiation_failed">Не вдалося виконати переговори щодо шифрування.</string> <string name="correct_name_to">Виправити ім\'я на %s?</string> - <string name="delete_messages__question">Видалити %d повідомлень?</string> + <string name="delete_messages__question">Видалити %d повідомлення?</string> <string name="connect_with_contact_name_question">Підключитися до %1$s?</string> - <string name="remove_member_button">Видалити учасника</string> - <string name="set_database_passphrase">Встановити пароль до бази даних</string> + <string name="remove_member_button">Вилучити учасника</string> + <string name="set_database_passphrase">Встановити ключову фразу бази даних</string> <string name="block_member_confirmation">Заблокувати</string> <string name="unblock_member_question">Розблокувати учасника?</string> <string name="blocked_items_description">%d повідомлень заблоковано</string> <string name="block_member_button">Заблокувати учасника</string> - <string name="open_database_folder">Відкрийте теку з базою даних</string> + <string name="open_database_folder">Відкрити папку бази даних</string> <string name="connect_plan_repeat_join_request">Повторити запит на приєднання?</string> - <string name="button_remove_member_question">Видалити учасника?</string> - <string name="delete_and_notify_contact">Видалити та повідомити контакт</string> - <string name="v5_3_new_interface_languages_descr">Арабська, Болгарська, Фінська, Іврит, Тайська та Українська – завдяки користувачам і Weblate.</string> - <string name="connect_plan_you_are_already_connecting_via_this_one_time_link">Ви вже підключаєтеся за цим одноразовим посиланням!</string> + <string name="button_remove_member_question">Вилучити учасника?</string> + <string name="delete_and_notify_contact">Видалити та сповістити контакт</string> + <string name="v5_3_new_interface_languages_descr">Арабська, болгарська, фінська, іврит, тайська та українська - завдяки користувачам і Weblate.</string> + <string name="connect_plan_you_are_already_connecting_via_this_one_time_link">Ви вже підключаєтеся через це одноразове посилання!</string> <string name="connect_plan_open_group">Відкрити групу</string> - <string name="unblock_member_desc">Будуть показані повідомлення від %s!</string> - <string name="v5_3_new_desktop_app_descr">Створіть новий профіль у десктопному застосунку. 💻</string> - <string name="error_sending_message_contact_invitation">Помилка надсилання запрошення</string> - <string name="passphrase_will_be_saved_in_settings">Після зміни пароля або перезапуску програми він буде збережений у налаштуваннях у вигляді відкритого тексту.</string> - <string name="non_content_uri_alert_text">Ви надали невірний шлях до файлу. Повідомте про проблему розробникам програми.</string> + <string name="unblock_member_desc">Повідомлення від %s будуть відображені!</string> + <string name="v5_3_new_desktop_app_descr">Створіть новий профіль у додатку для комп\'ютера. 💻</string> + <string name="error_sending_message_contact_invitation">Помилка при відправці запрошення</string> + <string name="passphrase_will_be_saved_in_settings">Після зміни ключової фрази або перезапуску додатка ключова фраза буде збережена в налаштуваннях як звичайний текст.</string> + <string name="non_content_uri_alert_text">Ви поділилися неправильним шляхом до файлу. Повідомте про цю проблему розробникам додатку.</string> <string name="block_member_question">Заблокувати учасника?</string> - <string name="rcv_group_events_count">%d групових подій</string> - <string name="invalid_name">Неправильне ім\'я!</string> - <string name="v5_3_simpler_incognito_mode_descr">Увімкніть інкогніто при підключенні.</string> + <string name="rcv_group_events_count">%d подій в групі</string> + <string name="invalid_name">Невірне ім\'я!</string> + <string name="v5_3_simpler_incognito_mode_descr">Перемикайте інкогніто під час підключення.</string> <string name="connect_plan_this_is_your_link_for_group_vName">Це ваше посилання для групи %1$s!</string> <string name="unblock_member_confirmation">Розблокувати</string> <string name="non_content_uri_alert_title">Неправильний шлях до файлу</string> - <string name="v5_3_discover_join_groups_descr">- підключитися до служби каталогів (БЕТА)! + <string name="v5_3_discover_join_groups_descr">- підключайтесь до служби каталогів (BETA)! \n- квитанції про доставку (до 20 учасників). -\n- швидше і стабільніше.</string> - <string name="settings_is_storing_in_clear_text">Пароль зберігається у налаштуваннях у вигляді відкритого тексту.</string> - <string name="connect_plan_you_have_already_requested_connection_via_this_address">Ви вже надсилали запит на підключення за цією адресою!</string> - <string name="member_contact_send_direct_message">надіслати пряме повідомлення</string> - <string name="terminal_always_visible">Показати консоль у новому вікні</string> - <string name="block_member_desc">Всі повідомлення від %s будуть приховані</string> - <string name="rcv_group_event_member_created_contact">підключений безпосередньо</string> +\n- швидше та надійніше.</string> + <string name="settings_is_storing_in_clear_text">Ключова фраза зберігається в налаштуваннях як звичайний текст.</string> + <string name="connect_plan_you_have_already_requested_connection_via_this_address">Ви вже подали запит на підключення за цією адресою!</string> + <string name="member_contact_send_direct_message">надіслати приватне повідомлення</string> + <string name="terminal_always_visible">Показувати консоль в новому вікні</string> + <string name="block_member_desc">Всі нові повідомлення від %s будуть приховані!</string> + <string name="rcv_group_event_member_created_contact">підключив(лась) безпосередньо</string> <string name="blocked_item_description">заблоковано</string> + <string name="v5_4_block_group_members">Блокувати учасників групи</string> + <string name="v5_4_incognito_groups_descr">Створіть групу, використовуючи випадковий профіль.</string> + <string name="connected_desktop">Підключений робочий стіл</string> + <string name="new_mobile_device">Новий мобільний пристрій</string> + <string name="multicast_connect_automatically">Підключати автоматично</string> + <string name="desktop_address">Адреса робочого столу</string> + <string name="only_one_device_can_work_at_the_same_time">Одночасно може працювати лише один пристрій</string> + <string name="v5_4_link_mobile_desktop">Посилання на мобільний та комп\'ютерний додатки! 🔗</string> + <string name="v5_4_link_mobile_desktop_descr">Через безпечний квантовостійкий протокол.</string> + <string name="open_on_mobile_and_scan_qr_code"><![CDATA[Відкрийте <i>Використовувати з робочого столу</i> у мобільному додатку і скануйте QR-код.]]></string> + <string name="v5_4_block_group_members_descr">Щоб приховати небажані повідомлення.</string> + <string name="desktop_incompatible_version">Несумісна версія</string> + <string name="new_desktop"><![CDATA[<i>(новий)</i>]]></string> + <string name="unlink_desktop_question">Відсунути відсилання до робочого столу?</string> + <string name="v5_4_better_groups">Кращі групи</string> + <string name="linked_desktop_options">Параметри пов\'язаних робочих столів</string> + <string name="linked_desktops">Пов\'язані робочі столи</string> + <string name="discover_on_network">Виявити через локальну мережу</string> + <string name="v5_4_incognito_groups">Інкогніто групи</string> + <string name="this_device">Цей пристрій</string> + <string name="remote_host_was_disconnected_toast"><![CDATA[Мобільний <b>%s</b> був відключений]]></string> + <string name="waiting_for_desktop">Очікування робочого столу…</string> + <string name="v5_4_better_groups_descr">Швидше приєднуйтесь та надійшовні повідомлення.</string> + <string name="linked_mobiles">Пов\'язані мобільні</string> + <string name="desktop_device">Робочий стіл</string> + <string name="connected_to_desktop">Підключено до робочого столу</string> + <string name="this_device_name">Назва цього пристрою</string> + <string name="loading_remote_file_title">Завантаження файлу</string> + <string name="connecting_to_desktop">Підключення до робочого столу</string> + <string name="found_desktop">Знайдено робочий стіл</string> + <string name="desktop_devices">Пристрої робочого столу</string> + <string name="not_compatible">Не сумісно!</string> + <string name="link_a_mobile">Зв\'язати з мобільним</string> + <string name="settings_section_title_use_from_desktop">Використовувати зі стаціонарного комп\'ютера</string> + <string name="connected_mobile">Підключений мобільний</string> + <string name="session_code">Код сеансу</string> + <string name="desktop_connection_terminated">Підключення завершено</string> + <string name="this_device_version"><![CDATA[<i>(цей пристрій v%s)</i>]]></string> + <string name="unlink_desktop">Відсунути відсилання</string> + <string name="this_device_name_shared_with_mobile">Назва пристрою буде надіслана підключеному мобільному клієнту.</string> + <string name="verify_code_on_mobile">Перевірте код на мобільному</string> + <string name="enter_this_device_name">Введіть назву цього пристрою…</string> + <string name="error">Помилка</string> + <string name="connect_to_desktop">Підключитися до робочого столу</string> + <string name="disconnect_remote_host">Відключити</string> + <string name="group_member_role_author">автор</string> + <string name="connected_to_mobile">Підключено до мобільного</string> + <string name="bad_desktop_address">Некоректна адреса робочого столу</string> + <string name="paste_desktop_address">Вставити адресу робочого столу</string> + <string name="verify_code_with_desktop">Перевірити код з робочим столом</string> + <string name="scan_qr_code_from_desktop">Сканувати QR-код з робочого столу</string> + <string name="devices">Пристрої</string> + <string name="multicast_discoverable_via_local_network">Виявлено через локальну мережу</string> + <string name="v5_4_more_things_descr">- за бажанням повідомляйте про видалених контактів. +\n- імена профілю з пробілами. +\n- та інше!</string> + <string name="scan_from_mobile">Сканувати з мобільного</string> + <string name="verify_connections">Перевірити підключення</string> + <string name="disconnect_desktop_question">Відключити робочий стіл?</string> + <string name="loading_remote_file_desc">Будь ласка, зачекайте, поки файл завантажується з підключеного мобільного</string> + <string name="desktop_app_version_is_incompatible">Версія робочого столу %s не сумісна з цим додатком.</string> + <string name="verify_connection">Перевірити підключення</string> </resources> \ No newline at end of file diff --git a/apps/multiplatform/common/src/commonMain/resources/MR/zh-rCN/strings.xml b/apps/multiplatform/common/src/commonMain/resources/MR/zh-rCN/strings.xml index c19a3960f7..b1baec68fc 100644 --- a/apps/multiplatform/common/src/commonMain/resources/MR/zh-rCN/strings.xml +++ b/apps/multiplatform/common/src/commonMain/resources/MR/zh-rCN/strings.xml @@ -67,7 +67,7 @@ <string name="connect_via_group_link">加群吗?</string> <string name="connect_via_link_or_qr">通过群组链接/二维码连接</string> <string name="always_use_relay">总是通过中继连接</string> - <string name="allow_your_contacts_irreversibly_delete">允许您的联系人不可撤回地删除已发送消息。</string> + <string name="allow_your_contacts_irreversibly_delete">允许您的联系人不不可逆地删除已发送消息。(24小时)</string> <string name="chat_preferences_contact_allows">联系人允许</string> <string name="allow_voice_messages_only_if">仅有您的联系人许可后才允许语音消息。</string> <string name="group_info_member_you">您: %1$s</string> @@ -88,8 +88,8 @@ <string name="rcv_group_event_group_deleted">已删除群组</string> <string name="delete_image">删除图片</string> <string name="allow_disappearing_messages_only_if">仅有您的联系人许可后才允许限时消息。</string> - <string name="allow_irreversible_message_deletion_only_if">仅有您的联系人许可后才允许不可撤回消息移除。</string> - <string name="allow_to_delete_messages">允许不可撤回地删除已发送消息。</string> + <string name="allow_irreversible_message_deletion_only_if">只有您的联系人同意才允许不可逆地删除消息。(24小时)</string> + <string name="allow_to_delete_messages">允许不可逆地删除已发送消息。(24小时)</string> <string name="users_delete_profile_for">为此删除聊天资料</string> <string name="delete_database">删除数据库</string> <string name="keychain_allows_to_receive_ntfs">在您重启应用程序或者更换密码后安卓密钥库系统用来安全地保存密码——来确保收到通知。</string> @@ -118,18 +118,16 @@ <string name="network_session_mode_entity_description">每个联系人和群组成员 <b>将使用单独的 TCP 连接(和 SOCKS 凭证)</b>。 \n<b>请注意</b>:如果您有很多连接,您的电池和流量消耗可能会大大增加,并且某些连接可能会失败。</string> <string name="back">返回</string> - <string name="add_new_contact_to_create_one_time_QR_code"><![CDATA[<b>添加新联系人</b>:为您的联系人创建一次性二维码。]]></string> <string name="onboarding_notifications_mode_off_desc"><![CDATA[<b> 最长续航 </b>。您只会在应用程序运行时收到通知(无后台服务)。]]></string> <string name="onboarding_notifications_mode_periodic_desc"><![CDATA[<b> 较长续航 </b>。后台服务每 10 分钟检查一次消息。您可能会错过来电或者紧急信息。]]></string> <string name="bold_text">加粗</string> - <string name="both_you_and_your_contacts_can_delete">您和您的联系人都可以永久删除已发送的消息。</string> + <string name="both_you_and_your_contacts_can_delete">您和您的联系人都可以不可逆地删除已发送的消息。(24小时)</string> <string name="both_you_and_your_contact_can_send_disappearing">您和您的联系人都可以发送限时消息。</string> <string name="both_you_and_your_contact_can_send_voice">您和您的联系人都可以发送语音消息。</string> <string name="it_can_disabled_via_settings_notifications_still_shown"><![CDATA[<b> 可以在设置里禁用它 </b> - 应用程序运行时仍会显示通知。]]></string> <string name="onboarding_notifications_mode_service_desc"><![CDATA[<b> 使用更多电量 </b>!后台服务始终运行——一旦收到消息,就会显示通知。]]></string> <string name="impossible_to_recover_passphrase"><![CDATA[<b>请注意</b>:如果您丢失密码,您将无法恢复或者更改密码。]]></string> <string name="call_already_ended">通话已结束!</string> - <string name="scan_QR_code_to_connect_to_contact_who_shows_QR_code"><![CDATA[<b>扫描二维码</b> :与向您展示二维码的联系人联系。]]></string> <string name="alert_title_cant_invite_contacts">无法邀请联系人!</string> <string name="invite_prohibited">无法邀请联系人!</string> <string name="cancel_verb">取消</string> @@ -338,7 +336,6 @@ <string name="create_secret_group_title">创建私密群组</string> <string name="v4_5_multiple_chat_profiles_descr">不同的名字、头像和传输隔离。</string> <string name="v4_4_french_interface">法语界面</string> - <string name="create_one_time_link">创建一次性邀请链接</string> <string name="how_to_use_simplex_chat">如何使用它</string> <string name="server_error">错误</string> <string name="display_name_connecting">连接中……</string> @@ -433,7 +430,7 @@ <string name="section_title_for_console">用于控制台</string> <string name="direct_messages_are_prohibited_in_chat">此群中禁止成员之间私信。</string> <string name="disappearing_messages_are_prohibited">该组禁止限时消息。</string> - <string name="group_members_can_delete">群组成员可以不可撤回地删除已发送的消息。</string> + <string name="group_members_can_delete">群组成员可以不可逆地删除已发送的消息。(24小时)</string> <string name="group_members_can_send_dms">群组成员可以私信。</string> <string name="v4_4_disappearing_messages">限时消息</string> <string name="v4_3_improved_privacy_and_security_desc">在最近的应用程序中隐藏应用程序屏幕。</string> @@ -463,7 +460,7 @@ <string name="icon_descr_add_members">邀请成员</string> <string name="group_member_status_left">已离开</string> <string name="theme_light">浅色</string> - <string name="message_deletion_prohibited">此聊天中禁止不可撤回消息移除。</string> + <string name="message_deletion_prohibited">此聊天中禁止不可逆消息移除。</string> <string name="v4_5_italian_interface">意大利语界面</string> <string name="incorrect_code">安全码不正确!</string> <string name="service_notifications_disabled">即时通知被禁用!</string> @@ -478,8 +475,8 @@ <string name="large_file">大文件!</string> <string name="invalid_contact_link">链接无效!</string> <string name="rcv_group_event_member_left">已离开</string> - <string name="message_deletion_prohibited_in_chat">此群组中禁止不可撤回消息移除。</string> - <string name="v4_3_irreversible_message_deletion">不可撤回消息移除</string> + <string name="message_deletion_prohibited_in_chat">此群组中禁止不可逆消息移除。</string> + <string name="v4_3_irreversible_message_deletion">不可逆消息移除</string> <string name="v4_4_live_messages">实时消息</string> <string name="notification_preview_mode_message">消息正文</string> <string name="callstate_waiting_for_confirmation">等待确认中……</string> @@ -516,11 +513,11 @@ <string name="callstate_starting">启动中……</string> <string name="prohibit_sending_disappearing_messages">禁止发送限时消息。</string> <string name="only_you_can_send_disappearing">只有您可以发送限时消息。</string> - <string name="only_your_contact_can_delete">只有您的联系人才能不可撤回地删除消息(您可以将它们标记为删除)。</string> + <string name="only_your_contact_can_delete">只有您的联系人能不可逆地删除消息(您可以将它们标记为删除)。(24小时)</string> <string name="prohibit_sending_disappearing">禁止发送限时消息。</string> <string name="notifications_will_be_hidden">通知只会在应用程序停止之前发送!</string> <string name="chat_preferences_no">否</string> - <string name="prohibit_message_deletion">禁止不可撤回消息删除。</string> + <string name="prohibit_message_deletion">禁止不可逆消息删除。</string> <string name="notification_new_contact_request">新联系人请求</string> <string name="callstate_waiting_for_answer">等待答复中……</string> <string name="la_notice_title_simplex_lock">SimpleX 锁定</string> @@ -587,7 +584,7 @@ \n给您的联系人</string> <string name="users_delete_with_connections">资料和服务器连接</string> <string name="update_network_settings_question">更新网络设置?</string> - <string name="only_you_can_delete_messages">只有您可以不可撤回地删除消息(您的联系人可以将它们标记为删除)。</string> + <string name="only_you_can_delete_messages">只有您可以不可逆地删除消息(您的联系人可以将它们标记为删除)。(24小时)</string> <string name="restart_the_app_to_create_a_new_chat_profile">重新启动应用程序以创建新的聊天资料。</string> <string name="error_smp_test_server_auth">服务器需要授权才能创建队列,检查密码</string> <string name="error_smp_test_failed_at_step">测试在步骤 %s 失败。</string> @@ -614,14 +611,14 @@ <string name="your_profile_is_stored_on_your_device">您的资料、联系人和发送的消息存储在您的设备上。</string> <string name="profile_is_only_shared_with_your_contacts">该资料仅与您的联系人共享。</string> <string name="chat_preferences_on">开启</string> - <string name="delete_chat_profile_action_cannot_be_undone_warning">此操作无法撤消——您的个人资料、联系人、消息和文件将不可撤回地丢失。</string> + <string name="delete_chat_profile_action_cannot_be_undone_warning">此操作无法撤消——您的个人资料、联系人、消息和文件将不可逆地丢失。</string> <string name="messages_section_description">此设置适用于您当前聊天资料中的消息</string> <string name="database_restore_error">恢复数据库错误</string> <string name="restore_database_alert_confirm">恢复</string> <string name="you_sent_group_invitation">您发送了群组邀请</string> <string name="you_rejected_group_invitation">您拒绝了群组邀请</string> <string name="your_current_chat_database_will_be_deleted_and_replaced_with_the_imported_one">您当前的聊天数据库将被删除并替换为导入的数据库。 -\n此操作无法撤消——您的个人资料、联系人、消息和文件将不可撤回地丢失。</string> +\n此操作无法撤消——您的个人资料、联系人、消息和文件将不可逆地丢失。</string> <string name="rcv_group_event_member_added">已邀请 %1$s</string> <string name="save_group_profile">保存群组资料</string> <string name="error_smp_test_certificate">服务器地址中的证书指纹可能不正确</string> @@ -776,7 +773,7 @@ <string name="strikethrough_text">删去</string> <string name="people_can_connect_only_via_links_you_share">人们只能通过您共享的链接与您建立联系。</string> <string name="next_generation_of_private_messaging">下一代私密通讯软件</string> - <string name="paste_the_link_you_received">粘贴收到的链接</string> + <string name="paste_the_link_you_received">粘贴您收到的链接</string> <string name="alert_title_skipped_messages">已跳过消息</string> <string name="settings_section_title_support">支持 SIMPLEX CHAT</string> <string name="send_link_previews">发送链接预览</string> @@ -981,7 +978,6 @@ <string name="v4_6_hidden_chat_profiles_descr">使用密码保护您的聊天资料!</string> <string name="confirm_password">确认密码</string> <string name="error_updating_user_privacy">更新用户隐私错误</string> - <string name="cant_delete_user_profile">无法删除用户资料!</string> <string name="error_saving_user_password">保存用户密码错误</string> <string name="enter_password_to_show">在搜索中输入密码</string> <string name="v4_6_group_welcome_message">群组欢迎消息</string> @@ -993,12 +989,10 @@ <string name="to_reveal_profile_enter_password">要显示您的隐藏的个人资料,请在您的聊天个人资料页面的搜索字段中输入完整密码。</string> <string name="save_welcome_message_question">保存欢迎信息?</string> <string name="tap_to_activate_profile">点击以激活个人资料。</string> - <string name="should_be_at_least_one_profile">应该至少有一个用户资料。</string> <string name="user_unhide">取消隐藏</string> <string name="v4_6_group_welcome_message_descr">设置向新成员显示的消息!</string> <string name="v4_6_audio_video_calls_descr">支持蓝牙和其他改进。</string> <string name="v4_6_chinese_spanish_interface_descr">感谢用户——通过 Weblate 做出贡献!</string> - <string name="should_be_at_least_one_visible_profile">应该至少有一个可见的用户资料。</string> <string name="user_unmute">解除静音</string> <string name="button_welcome_message">欢迎消息</string> <string name="you_will_still_receive_calls_and_ntfs">当静音配置文件处于活动状态时,您仍会收到来自静音配置文件的电话和通知。</string> @@ -1181,7 +1175,7 @@ <string name="sent_message">已发信息</string> <string name="edit_history">历史记录</string> <string name="send_disappearing_message_send">发送</string> - <string name="if_you_enter_passcode_data_removed">如果您在打开应用时输入该密码,所有应用程序数据将被不可撤回地删除!</string> + <string name="if_you_enter_passcode_data_removed">如果您在打开应用时输入该密码,所有应用程序数据将被不可逆地删除!</string> <string name="self_destruct_new_display_name">新的显示名:</string> <string name="info_row_moderated_at">已被管理员移除于</string> <string name="info_row_sent_at">已发送于</string> @@ -1407,14 +1401,14 @@ <string name="expand_verb">展开</string> <string name="connect_plan_repeat_connection_request">重复连接请求吗?</string> <string name="rcv_direct_event_contact_deleted">已删除联系人</string> - <string name="connect_plan_you_are_already_connecting_to_vName">你已经在连接到 %1$s。</string> + <string name="connect_plan_you_are_already_connecting_to_vName"><![CDATA[你已经在连接到 <b>%1$s</b>。]]></string> <string name="error_alert_title">错误</string> <string name="connect_plan_you_are_already_joining_the_group_via_this_link">你已经在通过此链接加入该群。</string> <string name="create_group_button">建群</string> <string name="create_another_profile_button">创建个人资料</string> <string name="group_members_2">%s 和 %s</string> <string name="connect_plan_join_your_group">加入你的群吗?</string> - <string name="connect_plan_you_are_already_joining_the_group_vName">你已经在加入 %1$s 群。</string> + <string name="connect_plan_you_are_already_joining_the_group_vName"><![CDATA[你已经在加入 <b>%1$s</b> 群。]]></string> <string name="connect_plan_this_is_your_own_one_time_link">这是你自己的一次性链接!</string> <string name="marked_deleted_items_description">%d 条消息被标记为删除</string> <string name="connect_plan_group_already_exists">群已存在!</string> @@ -1428,7 +1422,7 @@ <string name="unblock_member_button">解封成员</string> <string name="connect_plan_connect_to_yourself">连接到你自己?</string> <string name="contact_tap_to_connect">轻按连接</string> - <string name="connect_plan_you_are_already_in_group_vName">你已经在%1$s 群内。</string> + <string name="connect_plan_you_are_already_in_group_vName"><![CDATA[你已经在<b>%1$s</b> 群内。]]></string> <string name="connect_plan_this_is_your_own_simplex_address">这是你自己的 SimpleX 地址!</string> <string name="correct_name_to">更正名称为 %s?</string> <string name="delete_messages__question">删除 %d 条消息吗?</string> @@ -1449,7 +1443,7 @@ <string name="block_member_question">封禁成员吗?</string> <string name="rcv_group_events_count">%d 个群事件</string> <string name="invalid_name">无效名称!</string> - <string name="connect_plan_this_is_your_link_for_group_vName">这是给你的 %1$s 群链接!</string> + <string name="connect_plan_this_is_your_link_for_group_vName"><![CDATA[这是给你的 <b>%1$s</b> 群链接!]]></string> <string name="unblock_member_confirmation">解封</string> <string name="non_content_uri_alert_title">无效的文件路径</string> <string name="connect_plan_you_have_already_requested_connection_via_this_address">你已经请求通过此地址进行连接!</string> @@ -1509,7 +1503,7 @@ <string name="v5_4_block_group_members_descr">隐藏不需要的信息。</string> <string name="v5_4_better_groups">更佳的群组</string> <string name="v5_4_incognito_groups">匿名群组</string> - <string name="remote_host_was_disconnected_toast"><![CDATA[远程主机 <b>%s</b> 已断开连接]]></string> + <string name="remote_host_was_disconnected_toast"><![CDATA[移动主机 <b>%s</b> 连接断开]]></string> <string name="v5_4_better_groups_descr">加入速度更快、信息更可靠。</string> <string name="v5_4_more_things_descr">- 可选择通知已删除的联系人。 \n- 带空格的个人资料名称。 @@ -1521,4 +1515,121 @@ <string name="found_desktop">找到了桌面</string> <string name="not_compatible">不兼容!</string> <string name="multicast_discoverable_via_local_network">可通过本地网络发现</string> + <string name="refresh_qr_code">刷新</string> + <string name="create_chat_profile">创建聊天资料</string> + <string name="no_connected_mobile">没有已连接的移动设备</string> + <string name="disconnect_remote_hosts">断开移动设备连接</string> + <string name="random_port">随机</string> + <string name="open_port_in_firewall_desc">要允许移动应用连接到桌面,请在防火墙中打开此端口,如果你已启用了它</string> + <string name="open_port_in_firewall_title">在防火墙中打开端口</string> + <string name="app_was_crashed">查看崩溃</string> + <string name="moderated_items_description">%2$s 审核了 %1$d 条消息</string> + <string name="error_showing_content">显示内容出错</string> + <string name="error_showing_message">显示消息出错</string> + <string name="you_can_make_address_visible_via_settings">你可以通过设置让它对你的 SimpleX 联系人可见。</string> + <string name="recent_history_is_not_sent_to_new_members">未发送历史消息给新成员。</string> + <string name="retry_verb">重试</string> + <string name="camera_not_available">相机不可用</string> + <string name="enable_sending_recent_history">给新成员发送最多 100 条历史消息。</string> + <string name="add_contact_button_to_create_link_or_connect_via_link"><![CDATA[<b>添加联系人</b>: 来创建新的邀请链接,或通过你收到的链接进行连接。]]></string> + <string name="disable_sending_recent_history">不给新成员发送历史消息。</string> + <string name="or_show_this_qr_code">或者显示此码</string> + <string name="recent_history_is_sent_to_new_members">给新成员发送了最多 100 条历史消息。</string> + <string name="code_you_scanned_is_not_simplex_link_qr_code">您扫描的码不是 SimpleX 链接的二维码。</string> + <string name="the_text_you_pasted_is_not_a_link">您粘贴的文本不是 SimpleX 链接。</string> + <string name="enable_camera_access">启用相机访问</string> + <string name="you_can_view_invitation_link_again">您可以在连接详情中再次查看邀请链接。</string> + <string name="keep_unused_invitation_question">保留未使用的邀请吗?</string> + <string name="share_this_1_time_link">分享此一次性邀请链接</string> + <string name="create_group_button_to_create_new_group"><![CDATA[<b>建群</b>: 来建立新群。]]></string> + <string name="recent_history">可见的历史</string> + <string name="la_app_passcode">应用程序密码</string> + <string name="new_chat">新聊天</string> + <string name="loading_chats">加载聊天中…</string> + <string name="creating_link">创建链接中…</string> + <string name="or_scan_qr_code">或者扫描二维码</string> + <string name="invalid_qr_code">无效的二维码</string> + <string name="add_contact_tab">添加联系人</string> + <string name="tap_to_scan">轻按扫描</string> + <string name="keep_invitation_link">保留</string> + <string name="tap_to_paste_link">轻按粘贴链接</string> + <string name="search_or_paste_simplex_link">搜索或粘贴 SimpleX 链接</string> + <string name="chat_is_stopped_you_should_transfer_database">聊天已停止。如果你已经在另一台设备商使用过此数据库,你应该在启动聊天前将数据库传输回来。</string> + <string name="start_chat_question">启动聊天吗?</string> + <string name="agent_internal_error_title">内部错误</string> + <string name="agent_internal_error_desc">请将它报告给开发者: +\n%s</string> + <string name="agent_critical_error_desc">请将它报告给开发者: +\n%s +\n +\n建议重启应用。</string> + <string name="agent_critical_error_title">严重错误</string> + <string name="restart_chat_button">重启聊天</string> + <string name="show_internal_errors">显示内部错误</string> + <string name="remote_host_disconnected_from"><![CDATA[和移动主机<b>%s</b>的连接断开,原因是:%s]]></string> + <string name="remote_ctrl_disconnected_with_reason">断连原因:%s</string> + <string name="remote_ctrl_error_timeout">连接到桌面时超时</string> + <string name="remote_ctrl_error_busy">桌面繁忙</string> + <string name="remote_ctrl_error_bad_invitation">桌面邀请码错误</string> + <string name="remote_ctrl_error_inactive">桌面不活跃</string> + <string name="remote_ctrl_error_bad_state">到桌面的连接处于糟糕状态</string> + <string name="remote_ctrl_error_bad_version">已安装的桌面版本不受支持。请确保两台设备所安装版本形同</string> + <string name="remote_ctrl_error_disconnected">桌面连接已断开</string> + <string name="failed_to_create_user_invalid_title">无效的显示名!</string> + <string name="remote_ctrl_was_disconnected_title">连接停止</string> + <string name="remote_host_error_bad_version"><![CDATA[移动主机 <b>%s</b> 有一个不受支持的版本。请确保两台设备安装的版本相同]]></string> + <string name="remote_host_error_busy"><![CDATA[移动主机 <b>%s</b> 繁忙]]></string> + <string name="remote_host_error_inactive"><![CDATA[移动主机 <b>%s</b>不活跃]]></string> + <string name="remote_host_error_missing"><![CDATA[移动主机 <b>%s</b> 缺失]]></string> + <string name="remote_host_error_disconnected"><![CDATA[移动主机<b>%s</b>连接断开]]></string> + <string name="remote_host_was_disconnected_title">连接停止</string> + <string name="remote_host_error_bad_state"><![CDATA[到移动主机 <b>%s</b>的连接状态不佳]]></string> + <string name="remote_host_error_timeout"><![CDATA[连接到移动主机<b>%s</b>时超时]]></string> + <string name="failed_to_create_user_invalid_desc">显示名无效。请另选一个名称。</string> + <string name="possible_deadlock_title">死锁</string> + <string name="possible_deadlock_desc">代码执行花费的时间过久:%1$d秒。应用可能卡住了:%2$s</string> + <string name="possible_slow_function_title">慢函数</string> + <string name="show_slow_api_calls">显示缓慢的 API 调用</string> + <string name="past_member_vName">过往成员 %1$s</string> + <string name="group_member_status_unknown_short">未知</string> + <string name="group_member_status_unknown">未知状态</string> + <string name="developer_options_section">开发者选项</string> + <string name="possible_slow_function_desc">函数执行花费的时间过久:%1$d 秒: %2$s</string> + <string name="v5_5_message_delivery">改进了消息传递</string> + <string name="v5_5_join_group_conversation">加入群对话</string> + <string name="v5_5_simpler_connect_ui">粘贴链接以连接!</string> + <string name="v5_5_simpler_connect_ui_descr">搜索栏接受邀请链接。</string> + <string name="v5_5_private_notes_descr">加密的文件和媒体。</string> + <string name="v5_5_message_delivery_descr">降低了电量使用。</string> + <string name="clear_note_folder_warning">所有消息都将被删除 - 这无法被撤销!</string> + <string name="info_row_created_at">创建于</string> + <string name="share_text_created_at">创建于:%s</string> + <string name="v5_5_new_interface_languages">匈牙利语和土耳其语用户界面</string> + <string name="v5_5_private_notes">私密笔记</string> + <string name="v5_5_join_group_conversation_descr">最近历史和改进的目录机器人。</string> + <string name="profile_update_event_contact_name_changed">联系人姓名从 %1$s 改为了 %2$s</string> + <string name="profile_update_event_member_name_changed">成员姓名从 %1$s 改为了 %2$s</string> + <string name="profile_update_event_removed_address">删除了联系地址</string> + <string name="profile_update_event_removed_picture">删除了资料图片</string> + <string name="profile_update_event_set_new_address">设置新的联系地址</string> + <string name="profile_update_event_set_new_picture">设置新的资料图片</string> + <string name="profile_update_event_updated_profile">更新了资料</string> + <string name="error_creating_message">创建消息出错</string> + <string name="error_deleting_note_folder">删除私密笔记出错</string> + <string name="note_folder_local_display_name">私密笔记</string> + <string name="clear_note_folder_question">清除私密笔记?</string> + <string name="saved_message_title">已保存的消息</string> + <string name="blocked_by_admin_items_description">管理员封禁了 %d 条消息</string> + <string name="rcv_group_event_member_unblocked">已解封 %s</string> + <string name="block_for_all">为所有人封禁</string> + <string name="unblock_for_all">为所有人解封</string> + <string name="unblock_for_all_question">为所有其他成员解封该成员?</string> + <string name="member_blocked_by_admin">由管理员封禁</string> + <string name="blocked_by_admin_item_description">由管理员封禁</string> + <string name="rcv_group_event_member_blocked">已封禁 %s</string> + <string name="block_for_all_question">为所有其他成员封禁该成员?</string> + <string name="error_blocking_member_for_all">执行为所有人封禁时出错</string> + <string name="member_info_member_blocked">已封禁</string> + <string name="snd_group_event_member_blocked">你封禁了 %s</string> + <string name="snd_group_event_member_unblocked">你解封了 %s</string> </resources> \ No newline at end of file diff --git a/apps/multiplatform/common/src/commonMain/resources/MR/zh-rTW/strings.xml b/apps/multiplatform/common/src/commonMain/resources/MR/zh-rTW/strings.xml index 7ab98ca323..c9d4298bc7 100644 --- a/apps/multiplatform/common/src/commonMain/resources/MR/zh-rTW/strings.xml +++ b/apps/multiplatform/common/src/commonMain/resources/MR/zh-rTW/strings.xml @@ -47,8 +47,6 @@ <string name="allow_voice_messages_question">允許使用語音訊息?</string> <string name="cancel_verb">取消</string> <string name="icon_descr_cancel_live_message">取消實況訊息</string> - <string name="add_new_contact_to_create_one_time_QR_code"><![CDATA[<b>新增新的聯絡人</b>:建立你的一次性二維碼給你的聯絡人。]]></string> - <string name="scan_QR_code_to_connect_to_contact_who_shows_QR_code"><![CDATA[<b>掃描二維碼</b>:連接到向你出示二維碼的聯絡人。]]></string> <string name="choose_file">選擇檔案</string> <string name="use_camera_button">相機</string> <string name="from_gallery_button">從圖片庫選擇圖片</string> @@ -424,7 +422,6 @@ <string name="desktop_scan_QR_code_from_app_via_scan_QR_code"><![CDATA[💻 桌面版:在應用程式內掃描一個已存在的二維碼,透過 <b>掃描二維碼</b>。]]></string> <string name="icon_descr_settings">設定</string> <string name="this_QR_code_is_not_a_link">這個二維碼不是一個連結!</string> - <string name="create_one_time_link">建立一次性邀請連結</string> <string name="network_use_onion_hosts_prefer">當可行的時候</string> <string name="core_version">核心版本:v%s</string> <string name="core_simplexmq_version">simplexmq: v%s (%2s)</string> @@ -968,7 +965,6 @@ <string name="button_welcome_message">歡迎訊息</string> <string name="save_and_update_group_profile">儲存和更新群組配置檔案</string> <string name="save_welcome_message_question">儲存歡迎訊息?</string> - <string name="cant_delete_user_profile">無法刪除個人檔案!</string> <string name="user_hide">隱藏</string> <string name="make_profile_private">將個人資料設為私密!</string> <string name="v4_6_audio_video_calls">語音和視訊通話</string> @@ -994,10 +990,8 @@ <string name="v4_6_group_welcome_message_descr">設定向新成員顯示的訊息!</string> <string name="tap_to_activate_profile">點擊以激活配置檔案。</string> <string name="v4_6_audio_video_calls_descr">支援藍牙和其他改進。</string> - <string name="should_be_at_least_one_visible_profile">至少要有一個可見的個人檔案。</string> <string name="group_welcome_title">歡迎訊息</string> <string name="v4_6_chinese_spanish_interface_descr">感謝用戶-透過 Weblate 做出貢獻!</string> - <string name="should_be_at_least_one_profile">應該至少有一個個人檔案。</string> <string name="user_unmute">解除靜音</string> <string name="you_will_still_receive_calls_and_ntfs">當靜音配置檔案處於活動狀態時,你仍會接收來自靜音配置檔案的通話和通知。</string> <string name="user_unhide">取消隱藏</string> diff --git a/apps/multiplatform/common/src/desktopMain/kotlin/chat/simplex/common/DesktopApp.kt b/apps/multiplatform/common/src/desktopMain/kotlin/chat/simplex/common/DesktopApp.kt index 57371e25a7..6e7945d8ca 100644 --- a/apps/multiplatform/common/src/desktopMain/kotlin/chat/simplex/common/DesktopApp.kt +++ b/apps/multiplatform/common/src/desktopMain/kotlin/chat/simplex/common/DesktopApp.kt @@ -186,7 +186,7 @@ private fun ApplicationScope.AppWindow(closedByError: MutableState<Boolean>) { } } // Reload all strings in all @Composable's after language change at runtime - if (remember { ChatController.appPrefs.terminalAlwaysVisible.state }.value && remember { ChatController.appPrefs.appLanguage.state }.value != "") { + if (remember { ChatController.appPrefs.developerTools.state }.value && remember { ChatController.appPrefs.terminalAlwaysVisible.state }.value && remember { ChatController.appPrefs.appLanguage.state }.value != "") { var hiddenUntilRestart by remember { mutableStateOf(false) } if (!hiddenUntilRestart) { val cWindowState = rememberWindowState(placement = WindowPlacement.Floating, width = DEFAULT_START_MODAL_WIDTH, height = 768.dp) diff --git a/apps/multiplatform/common/src/desktopMain/kotlin/chat/simplex/common/platform/AppCommon.desktop.kt b/apps/multiplatform/common/src/desktopMain/kotlin/chat/simplex/common/platform/AppCommon.desktop.kt index b2b27f9d1f..72aca181b3 100644 --- a/apps/multiplatform/common/src/desktopMain/kotlin/chat/simplex/common/platform/AppCommon.desktop.kt +++ b/apps/multiplatform/common/src/desktopMain/kotlin/chat/simplex/common/platform/AppCommon.desktop.kt @@ -2,8 +2,7 @@ package chat.simplex.common.platform import chat.simplex.common.model.* import chat.simplex.common.views.call.RcvCallInvitation -import chat.simplex.common.views.helpers.generalGetString -import chat.simplex.common.views.helpers.withBGApi +import chat.simplex.common.views.helpers.* import java.util.* import chat.simplex.res.MR @@ -26,9 +25,8 @@ fun initApp() { override fun showMessage(title: String, text: String) = chat.simplex.common.model.NtfManager.showMessage(title, text) } applyAppLocale() - withBGApi { - initChatController() - runMigrations() + if (DatabaseUtils.ksSelfDestructPassword.get() == null) { + initChatControllerAndRunMigrations() } // LALAL //testCrypto() diff --git a/apps/multiplatform/common/src/desktopMain/kotlin/chat/simplex/common/platform/Modifier.desktop.kt b/apps/multiplatform/common/src/desktopMain/kotlin/chat/simplex/common/platform/Modifier.desktop.kt index 6f317acb92..9245f2b950 100644 --- a/apps/multiplatform/common/src/desktopMain/kotlin/chat/simplex/common/platform/Modifier.desktop.kt +++ b/apps/multiplatform/common/src/desktopMain/kotlin/chat/simplex/common/platform/Modifier.desktop.kt @@ -4,6 +4,8 @@ import androidx.compose.foundation.contextMenuOpenDetector import androidx.compose.runtime.Composable import androidx.compose.ui.* import androidx.compose.ui.graphics.painter.Painter +import androidx.compose.ui.input.pointer.PointerIcon +import androidx.compose.ui.input.pointer.pointerHoverIcon import java.io.File import java.net.URI @@ -36,3 +38,5 @@ onExternalDrag(enabled) { } actual fun Modifier.onRightClick(action: () -> Unit): Modifier = contextMenuOpenDetector { action() } + +actual fun Modifier.desktopPointerHoverIconHand(): Modifier = Modifier.pointerHoverIcon(PointerIcon.Hand) diff --git a/apps/multiplatform/common/src/desktopMain/kotlin/chat/simplex/common/platform/PlatformTextField.desktop.kt b/apps/multiplatform/common/src/desktopMain/kotlin/chat/simplex/common/platform/PlatformTextField.desktop.kt index 8016b18b12..3ca74a6d84 100644 --- a/apps/multiplatform/common/src/desktopMain/kotlin/chat/simplex/common/platform/PlatformTextField.desktop.kt +++ b/apps/multiplatform/common/src/desktopMain/kotlin/chat/simplex/common/platform/PlatformTextField.desktop.kt @@ -167,7 +167,8 @@ actual fun PlatformTextField( decorationBox = { innerTextField -> Surface( shape = RoundedCornerShape(18.dp), - border = BorderStroke(1.dp, MaterialTheme.colors.secondary) + border = BorderStroke(1.dp, MaterialTheme.colors.secondary), + contentColor = LocalContentColor.current ) { Row( Modifier.background(MaterialTheme.colors.background), diff --git a/apps/multiplatform/common/src/desktopMain/kotlin/chat/simplex/common/platform/RecAndPlay.desktop.kt b/apps/multiplatform/common/src/desktopMain/kotlin/chat/simplex/common/platform/RecAndPlay.desktop.kt index b6d18aaf8b..50d143aaf5 100644 --- a/apps/multiplatform/common/src/desktopMain/kotlin/chat/simplex/common/platform/RecAndPlay.desktop.kt +++ b/apps/multiplatform/common/src/desktopMain/kotlin/chat/simplex/common/platform/RecAndPlay.desktop.kt @@ -211,15 +211,13 @@ actual object SoundPlayer: SoundPlayerInterface { var playing = false override fun start(scope: CoroutineScope, sound: Boolean) { - withBGApi { - val tmpFile = File(tmpDir, UUID.randomUUID().toString()) - tmpFile.deleteOnExit() - SoundPlayer::class.java.getResource("/media/ring_once.mp3").openStream()!!.use { it.copyTo(tmpFile.outputStream()) } - playing = true - while (playing) { - if (sound) { - AudioPlayer.play(CryptoFile.plain(tmpFile.absolutePath), mutableStateOf(true), mutableStateOf(0), mutableStateOf(0), true) - } + val tmpFile = File(tmpDir, UUID.randomUUID().toString()) + tmpFile.deleteOnExit() + SoundPlayer::class.java.getResource("/media/ring_once.mp3").openStream()!!.use { it.copyTo(tmpFile.outputStream()) } + playing = true + scope.launch { + while (playing && sound) { + AudioPlayer.play(CryptoFile.plain(tmpFile.absolutePath), mutableStateOf(true), mutableStateOf(0), mutableStateOf(0), true) delay(3500) } } diff --git a/apps/multiplatform/common/src/desktopMain/kotlin/chat/simplex/common/platform/Share.desktop.kt b/apps/multiplatform/common/src/desktopMain/kotlin/chat/simplex/common/platform/Share.desktop.kt index b40b892de4..d1442bc5e3 100644 --- a/apps/multiplatform/common/src/desktopMain/kotlin/chat/simplex/common/platform/Share.desktop.kt +++ b/apps/multiplatform/common/src/desktopMain/kotlin/chat/simplex/common/platform/Share.desktop.kt @@ -4,8 +4,7 @@ import androidx.compose.ui.platform.ClipboardManager import androidx.compose.ui.platform.UriHandler import androidx.compose.ui.text.AnnotatedString import chat.simplex.common.model.* -import chat.simplex.common.views.helpers.generalGetString -import chat.simplex.common.views.helpers.withApi +import chat.simplex.common.views.helpers.* import java.io.File import java.net.URI import java.net.URLEncoder @@ -23,7 +22,7 @@ actual fun ClipboardManager.shareText(text: String) { } actual fun shareFile(text: String, fileSource: CryptoFile) { - withApi { + withLongRunningApi { FileChooserLauncher(false) { to: URI? -> if (to != null) { val absolutePath = if (fileSource.isAbsolutePath) fileSource.filePath else getAppFilePath(fileSource.filePath) diff --git a/apps/multiplatform/common/src/desktopMain/kotlin/chat/simplex/common/platform/VideoPlayer.desktop.kt b/apps/multiplatform/common/src/desktopMain/kotlin/chat/simplex/common/platform/VideoPlayer.desktop.kt index ec487bc884..dcae784662 100644 --- a/apps/multiplatform/common/src/desktopMain/kotlin/chat/simplex/common/platform/VideoPlayer.desktop.kt +++ b/apps/multiplatform/common/src/desktopMain/kotlin/chat/simplex/common/platform/VideoPlayer.desktop.kt @@ -29,7 +29,7 @@ actual class VideoPlayer actual constructor( override val brokenVideo: MutableState<Boolean> = mutableStateOf(false) override val videoPlaying: MutableState<Boolean> = mutableStateOf(false) override val progress: MutableState<Long> = mutableStateOf(0L) - override val duration: MutableState<Long> = mutableStateOf(0L) + override val duration: MutableState<Long> = mutableStateOf(defaultDuration) override val preview: MutableState<ImageBitmap> = mutableStateOf(defaultPreview) val mediaPlayerComponent by lazy { runBlocking(playerThread.asCoroutineDispatcher()) { getOrCreatePlayer() } } diff --git a/apps/multiplatform/common/src/desktopMain/kotlin/chat/simplex/common/views/chat/item/ChatItemView.desktop.kt b/apps/multiplatform/common/src/desktopMain/kotlin/chat/simplex/common/views/chat/item/ChatItemView.desktop.kt index 905a6e3520..29e9d5bae1 100644 --- a/apps/multiplatform/common/src/desktopMain/kotlin/chat/simplex/common/views/chat/item/ChatItemView.desktop.kt +++ b/apps/multiplatform/common/src/desktopMain/kotlin/chat/simplex/common/views/chat/item/ChatItemView.desktop.kt @@ -35,14 +35,14 @@ actual fun SaveContentItemAction(cItem: ChatItem, saveFileLauncher: FileChooserL ItemAction(stringResource(MR.strings.save_verb), painterResource(if (cItem.file?.fileSource?.cryptoArgs == null) MR.images.ic_download else MR.images.ic_lock_open_right), onClick = { val saveIfExists = { when (cItem.content.msgContent) { - is MsgContent.MCImage, is MsgContent.MCFile, is MsgContent.MCVoice, is MsgContent.MCVideo -> withApi { saveFileLauncher.launch(cItem.file?.fileName ?: "") } + is MsgContent.MCImage, is MsgContent.MCFile, is MsgContent.MCVoice, is MsgContent.MCVideo -> withLongRunningApi { saveFileLauncher.launch(cItem.file?.fileName ?: "") } else -> {} } showMenu.value = false } var fileSource = getLoadedFileSource(cItem.file) if (chatModel.connectedToRemote() && fileSource == null) { - withBGApi { + withLongRunningApi(slow = 60_000, deadlock = 600_000) { cItem.file?.loadRemoteFile(true) fileSource = getLoadedFileSource(cItem.file) saveIfExists() @@ -51,7 +51,7 @@ actual fun SaveContentItemAction(cItem: ChatItem, saveFileLauncher: FileChooserL }) } -actual fun copyItemToClipboard(cItem: ChatItem, clipboard: ClipboardManager) = withBGApi { +actual fun copyItemToClipboard(cItem: ChatItem, clipboard: ClipboardManager) = withLongRunningApi(slow = 60_000, deadlock = 600_000) { var fileSource = getLoadedFileSource(cItem.file) if (chatModel.connectedToRemote() && fileSource == null) { cItem.file?.loadRemoteFile(true) @@ -63,10 +63,10 @@ actual fun copyItemToClipboard(cItem: ChatItem, clipboard: ClipboardManager) = w val tmpFile = File(tmpDir, fileSource.filePath) tmpFile.deleteOnExit() try { - decryptCryptoFile(getAppFilePath(fileSource.filePath), fileSource.cryptoArgs ?: return@withBGApi, tmpFile.absolutePath) + decryptCryptoFile(getAppFilePath(fileSource.filePath), fileSource.cryptoArgs ?: return@withLongRunningApi, tmpFile.absolutePath) } catch (e: Exception) { Log.e(TAG, "Unable to decrypt crypto file: " + e.stackTraceToString()) - return@withBGApi + return@withLongRunningApi } tmpFile.absolutePath } else { diff --git a/apps/multiplatform/common/src/desktopMain/kotlin/chat/simplex/common/views/chatlist/ChatListNavLinkView.desktop.kt b/apps/multiplatform/common/src/desktopMain/kotlin/chat/simplex/common/views/chatlist/ChatListNavLinkView.desktop.kt index 6c37c93ccc..189f1842dd 100644 --- a/apps/multiplatform/common/src/desktopMain/kotlin/chat/simplex/common/views/chatlist/ChatListNavLinkView.desktop.kt +++ b/apps/multiplatform/common/src/desktopMain/kotlin/chat/simplex/common/views/chatlist/ChatListNavLinkView.desktop.kt @@ -1,5 +1,6 @@ package chat.simplex.common.views.chatlist +import SectionDivider import androidx.compose.foundation.* import androidx.compose.foundation.interaction.InteractionSource import androidx.compose.foundation.layout.* @@ -8,7 +9,6 @@ import androidx.compose.material.MaterialTheme import androidx.compose.runtime.* import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier -import androidx.compose.ui.graphics.Color import androidx.compose.ui.graphics.drawscope.ContentDrawScope import androidx.compose.ui.unit.dp import chat.simplex.common.platform.onRightClick @@ -32,16 +32,16 @@ actual fun ChatListNavLinkLayout( click: () -> Unit, dropdownMenuItems: (@Composable () -> Unit)?, showMenu: MutableState<Boolean>, - stopped: Boolean, - selectedChat: State<Boolean> + disabled: Boolean, + selectedChat: State<Boolean>, + nextChatSelected: State<Boolean>, ) { var modifier = Modifier.fillMaxWidth() - if (!stopped) modifier = modifier - .background(color = if (selectedChat.value) MaterialTheme.colors.background.mixWith(MaterialTheme.colors.onBackground, 0.95f) else Color.Unspecified) + if (!disabled) modifier = modifier .combinedClickable(onClick = click, onLongClick = { showMenu.value = true }) .onRightClick { showMenu.value = true } CompositionLocalProvider( - LocalIndication provides if (selectedChat.value && !stopped) NoIndication else LocalIndication.current + LocalIndication provides if (selectedChat.value && !disabled) NoIndication else LocalIndication.current ) { Box(modifier) { Row( @@ -52,10 +52,17 @@ actual fun ChatListNavLinkLayout( ) { chatLinkPreview() } + if (selectedChat.value) { + Box(Modifier.matchParentSize().background(MaterialTheme.colors.onBackground.copy(0.05f))) + } if (dropdownMenuItems != null) { DefaultDropdownMenu(showMenu, dropdownMenuItems = dropdownMenuItems) } } } - Divider() + if (selectedChat.value || nextChatSelected.value) { + Divider() + } else { + SectionDivider() + } } diff --git a/apps/multiplatform/common/src/desktopMain/kotlin/chat/simplex/common/views/chatlist/ChatListView.desktop.kt b/apps/multiplatform/common/src/desktopMain/kotlin/chat/simplex/common/views/chatlist/ChatListView.desktop.kt index 61e0e0d3ce..13d2f8b1e4 100644 --- a/apps/multiplatform/common/src/desktopMain/kotlin/chat/simplex/common/views/chatlist/ChatListView.desktop.kt +++ b/apps/multiplatform/common/src/desktopMain/kotlin/chat/simplex/common/views/chatlist/ChatListView.desktop.kt @@ -43,7 +43,7 @@ actual fun DesktopActiveCallOverlayLayout(newChatSheetState: MutableStateFlow<An .combinedClickable(onClick = { val chat = chatModel.getChat(call.contact.id) if (chat != null) { - withApi { + withBGApi { openChat(chat.remoteHostId, chat.chatInfo, chatModel) } } diff --git a/apps/multiplatform/common/src/desktopMain/kotlin/chat/simplex/common/views/database/DatabaseView.desktop.kt b/apps/multiplatform/common/src/desktopMain/kotlin/chat/simplex/common/views/database/DatabaseView.desktop.kt index 10e9f9f3c3..889ac98e2d 100644 --- a/apps/multiplatform/common/src/desktopMain/kotlin/chat/simplex/common/views/database/DatabaseView.desktop.kt +++ b/apps/multiplatform/common/src/desktopMain/kotlin/chat/simplex/common/views/database/DatabaseView.desktop.kt @@ -2,7 +2,7 @@ package chat.simplex.common.views.database import androidx.compose.runtime.mutableStateOf import chat.simplex.common.platform.chatModel -import chat.simplex.common.views.helpers.withApi +import chat.simplex.common.views.helpers.withBGApi import kotlinx.coroutines.delay import kotlinx.datetime.Instant @@ -12,7 +12,7 @@ actual fun restartChatOrApp() { startChat(chatModel, mutableStateOf(Instant.DISTANT_PAST), chatModel.chatDbChanged) } else { authStopChat(chatModel) { - withApi { + withBGApi { // adding delay in order to prevent locked database by previous initialization delay(1000) chatModel.chatDbChanged.value = true diff --git a/apps/multiplatform/common/src/desktopMain/kotlin/chat/simplex/common/views/helpers/DefaultDialog.desktop.kt b/apps/multiplatform/common/src/desktopMain/kotlin/chat/simplex/common/views/helpers/DefaultDialog.desktop.kt index 79fcda7a50..7341c6af23 100644 --- a/apps/multiplatform/common/src/desktopMain/kotlin/chat/simplex/common/views/helpers/DefaultDialog.desktop.kt +++ b/apps/multiplatform/common/src/desktopMain/kotlin/chat/simplex/common/views/helpers/DefaultDialog.desktop.kt @@ -2,8 +2,7 @@ package chat.simplex.common.views.helpers import androidx.compose.foundation.* import androidx.compose.foundation.shape.RoundedCornerShape -import androidx.compose.material.MaterialTheme -import androidx.compose.material.Surface +import androidx.compose.material.* import androidx.compose.runtime.* import androidx.compose.ui.Modifier import androidx.compose.ui.input.key.* @@ -39,7 +38,8 @@ actual fun DefaultDialog( ) { Surface( Modifier - .border(border = BorderStroke(1.dp, MaterialTheme.colors.secondary.copy(alpha = 0.3F)), shape = RoundedCornerShape(8)) + .border(border = BorderStroke(1.dp, MaterialTheme.colors.secondary.copy(alpha = 0.3F)), shape = RoundedCornerShape(8)), + contentColor = LocalContentColor.current ) { content() } diff --git a/apps/multiplatform/common/src/desktopMain/kotlin/chat/simplex/common/views/helpers/GetImageView.desktop.kt b/apps/multiplatform/common/src/desktopMain/kotlin/chat/simplex/common/views/helpers/GetImageView.desktop.kt index 979857f044..59865dd66f 100644 --- a/apps/multiplatform/common/src/desktopMain/kotlin/chat/simplex/common/views/helpers/GetImageView.desktop.kt +++ b/apps/multiplatform/common/src/desktopMain/kotlin/chat/simplex/common/views/helpers/GetImageView.desktop.kt @@ -45,7 +45,7 @@ actual fun GetImageBottomSheet( } val pickImageLauncher = rememberFileChooserLauncher(true, null, processPickedImage) ActionButton(null, stringResource(MR.strings.from_gallery_button), icon = painterResource(MR.images.ic_image)) { - withApi { pickImageLauncher.launch("image/*") } + withLongRunningApi { pickImageLauncher.launch("image/*") } } } } diff --git a/apps/multiplatform/common/src/desktopMain/kotlin/chat/simplex/common/views/helpers/Utils.desktop.kt b/apps/multiplatform/common/src/desktopMain/kotlin/chat/simplex/common/views/helpers/Utils.desktop.kt index 19c9fc0fd7..9fa93cdfdf 100644 --- a/apps/multiplatform/common/src/desktopMain/kotlin/chat/simplex/common/views/helpers/Utils.desktop.kt +++ b/apps/multiplatform/common/src/desktopMain/kotlin/chat/simplex/common/views/helpers/Utils.desktop.kt @@ -1,14 +1,20 @@ package chat.simplex.common.views.helpers +import androidx.compose.runtime.* import androidx.compose.ui.graphics.* +import androidx.compose.ui.platform.LocalClipboardManager import androidx.compose.ui.text.* import androidx.compose.ui.text.font.FontStyle import androidx.compose.ui.text.font.FontWeight +import androidx.compose.ui.text.style.TextDecoration import androidx.compose.ui.unit.Density import chat.simplex.common.model.CIFile import chat.simplex.common.model.readCryptoFile import chat.simplex.common.platform.* import chat.simplex.common.simplexWindowState +import kotlinx.coroutines.delay +import java.io.ByteArrayInputStream +import java.io.File import java.io.* import java.net.URI import javax.imageio.ImageIO @@ -17,6 +23,7 @@ import kotlin.io.encoding.ExperimentalEncodingApi private val bStyle = SpanStyle(fontWeight = FontWeight.Bold) private val iStyle = SpanStyle(fontStyle = FontStyle.Italic) +private val uStyle = SpanStyle(textDecoration = TextDecoration.Underline) private fun fontStyle(color: String) = SpanStyle(color = Color(color.replace("#", "ff").toLongOrNull(16) ?: Color.White.toArgb().toLong())) @@ -54,6 +61,22 @@ actual fun escapedHtmlToAnnotatedString(text: String, density: Density): Annotat } break } + text.substringSafe(innerI, 2) == "u>" -> { + val textStart = innerI + 2 + for (insideTagI in textStart until text.length) { + if (text[insideTagI] == '<') { + withStyle(uStyle) { append(text.substring(textStart, insideTagI)) } + skipTil = insideTagI + 4 + break + } + } + break + } + text.substringSafe(innerI, 3) == "br>" -> { + val textStart = innerI + 3 + append("\n") + skipTil = textStart + } text.substringSafe(innerI, 4) == "font" -> { var textStart = innerI + 5 var color = "#000000" @@ -85,6 +108,18 @@ actual fun escapedHtmlToAnnotatedString(text: String, density: Density): Annotat AnnotatedString(text) } +@Composable +actual fun SetupClipboardListener() { + val clipboard = LocalClipboardManager.current + chatModel.clipboardHasText.value = clipboard.hasText() + LaunchedEffect(Unit) { + while (true) { + delay(1000) + chatModel.clipboardHasText.value = clipboard.hasText() + } + } +} + actual fun getAppFileUri(fileName: String): URI { val rh = chatModel.currentRemoteHost.value return if (rh == null) { diff --git a/apps/multiplatform/common/src/desktopMain/kotlin/chat/simplex/common/views/newchat/ConnectViaLinkView.desktop.kt b/apps/multiplatform/common/src/desktopMain/kotlin/chat/simplex/common/views/newchat/ConnectViaLinkView.desktop.kt deleted file mode 100644 index 72d9678154..0000000000 --- a/apps/multiplatform/common/src/desktopMain/kotlin/chat/simplex/common/views/newchat/ConnectViaLinkView.desktop.kt +++ /dev/null @@ -1,11 +0,0 @@ -package chat.simplex.common.views.newchat - -import androidx.compose.runtime.* -import chat.simplex.common.model.ChatModel -import chat.simplex.common.model.RemoteHostInfo - -@Composable -actual fun ConnectViaLinkView(m: ChatModel, rh: RemoteHostInfo?, close: () -> Unit) { - // TODO this should close if remote host changes in model - PasteToConnectView(m, rh, close) -} diff --git a/apps/multiplatform/common/src/desktopMain/kotlin/chat/simplex/common/views/newchat/QRCodeScanner.desktop.kt b/apps/multiplatform/common/src/desktopMain/kotlin/chat/simplex/common/views/newchat/QRCodeScanner.desktop.kt index 16d35b5b8d..0142afb4ac 100644 --- a/apps/multiplatform/common/src/desktopMain/kotlin/chat/simplex/common/views/newchat/QRCodeScanner.desktop.kt +++ b/apps/multiplatform/common/src/desktopMain/kotlin/chat/simplex/common/views/newchat/QRCodeScanner.desktop.kt @@ -1,8 +1,13 @@ package chat.simplex.common.views.newchat +import androidx.compose.foundation.layout.PaddingValues import androidx.compose.runtime.* @Composable -actual fun QRCodeScanner(onBarcode: (String) -> Unit) { +actual fun QRCodeScanner( + showQRCodeScanner: MutableState<Boolean>, + padding: PaddingValues, + onBarcode: (String) -> Unit +) { //LALAL } diff --git a/apps/multiplatform/common/src/desktopMain/kotlin/chat/simplex/common/views/newchat/ScanToConnectView.desktop.kt b/apps/multiplatform/common/src/desktopMain/kotlin/chat/simplex/common/views/newchat/ScanToConnectView.desktop.kt deleted file mode 100644 index 7579f09fa5..0000000000 --- a/apps/multiplatform/common/src/desktopMain/kotlin/chat/simplex/common/views/newchat/ScanToConnectView.desktop.kt +++ /dev/null @@ -1,15 +0,0 @@ -package chat.simplex.common.views.newchat - -import androidx.compose.runtime.Composable -import chat.simplex.common.model.ChatModel -import chat.simplex.common.model.RemoteHostInfo - -@Composable -actual fun ScanToConnectView(chatModel: ChatModel, rh: RemoteHostInfo?, close: () -> Unit) { - ConnectContactLayout( - chatModel = chatModel, - rh = rh, - incognitoPref = chatModel.controller.appPrefs.incognito, - close = close - ) -} diff --git a/apps/multiplatform/common/src/desktopMain/kotlin/chat/simplex/common/views/usersettings/SettingsView.desktop.kt b/apps/multiplatform/common/src/desktopMain/kotlin/chat/simplex/common/views/usersettings/SettingsView.desktop.kt index 95a079fe1b..5a42b4b756 100644 --- a/apps/multiplatform/common/src/desktopMain/kotlin/chat/simplex/common/views/usersettings/SettingsView.desktop.kt +++ b/apps/multiplatform/common/src/desktopMain/kotlin/chat/simplex/common/views/usersettings/SettingsView.desktop.kt @@ -3,6 +3,7 @@ package chat.simplex.common.views.usersettings import SectionView import androidx.compose.runtime.Composable import chat.simplex.common.model.ChatModel +import chat.simplex.common.views.helpers.ModalData import chat.simplex.res.MR import dev.icerock.moko.resources.compose.painterResource import dev.icerock.moko.resources.compose.stringResource @@ -10,7 +11,7 @@ import dev.icerock.moko.resources.compose.stringResource @Composable actual fun SettingsSectionApp( showSettingsModal: (@Composable (ChatModel) -> Unit) -> (() -> Unit), - showCustomModal: (@Composable (ChatModel, () -> Unit) -> Unit) -> (() -> Unit), + showCustomModal: (@Composable ModalData.(ChatModel, () -> Unit) -> Unit) -> (() -> Unit), showVersion: () -> Unit, withAuth: (title: String, desc: String, block: () -> Unit) -> Unit ) { diff --git a/apps/multiplatform/desktop/build.gradle.kts b/apps/multiplatform/desktop/build.gradle.kts index a784d5c5fe..4f5536a25b 100644 --- a/apps/multiplatform/desktop/build.gradle.kts +++ b/apps/multiplatform/desktop/build.gradle.kts @@ -102,9 +102,8 @@ compose { // Packaging requires to have version like MAJOR.MINOR.PATCH var adjustedVersion = rootProject.extra["desktop.version_name"] as String adjustedVersion = adjustedVersion.replace(Regex("[^0-9.]"), "") - if (adjustedVersion.split(".").size != 3) { - adjustedVersion += ".0" - } + val split = adjustedVersion.split(".") + adjustedVersion = split[0] + "." + (split.getOrNull(1) ?: "0") + "." + (split.getOrNull(2) ?: "0") version = adjustedVersion } } diff --git a/apps/multiplatform/gradle.properties b/apps/multiplatform/gradle.properties index f4de8d5188..0dafb95b52 100644 --- a/apps/multiplatform/gradle.properties +++ b/apps/multiplatform/gradle.properties @@ -25,11 +25,11 @@ android.nonTransitiveRClass=true android.enableJetifier=true kotlin.mpp.androidSourceSetLayoutVersion=2 -android.version_name=5.4.3 -android.version_code=169 +android.version_name=5.5 +android.version_code=175 -desktop.version_name=5.4.3 -desktop.version_code=22 +desktop.version_name=5.5 +desktop.version_code=26 kotlin.version=1.8.20 gradle.plugin.version=7.4.2 diff --git a/apps/simplex-broadcast-bot/src/Broadcast/Options.hs b/apps/simplex-broadcast-bot/src/Broadcast/Options.hs index 9a79af4b48..bce0f94972 100644 --- a/apps/simplex-broadcast-bot/src/Broadcast/Options.hs +++ b/apps/simplex-broadcast-bot/src/Broadcast/Options.hs @@ -10,7 +10,7 @@ import Data.Maybe (fromMaybe) import Options.Applicative import Simplex.Chat.Bot.KnownContacts import Simplex.Chat.Controller (updateStr, versionNumber, versionString) -import Simplex.Chat.Options (ChatOpts (..), CoreChatOpts, coreChatOptsP) +import Simplex.Chat.Options (ChatCmdLog (..), ChatOpts (..), CoreChatOpts, coreChatOptsP) data BroadcastBotOpts = BroadcastBotOpts { coreOptions :: CoreChatOpts, @@ -77,6 +77,7 @@ mkChatOpts BroadcastBotOpts {coreOptions} = deviceName = Nothing, chatCmd = "", chatCmdDelay = 3, + chatCmdLog = CCLNone, chatServerPort = Nothing, optFilesFolder = Nothing, showReactions = False, diff --git a/apps/simplex-chat/Main.hs b/apps/simplex-chat/Main.hs index ccfc6a4848..f47bd6c7c4 100644 --- a/apps/simplex-chat/Main.hs +++ b/apps/simplex-chat/Main.hs @@ -1,13 +1,15 @@ +{-# LANGUAGE DuplicateRecordFields #-} {-# LANGUAGE NamedFieldPuns #-} module Main where -import Control.Concurrent (threadDelay) -import Control.Concurrent.STM.TVar (readTVarIO) +import Control.Concurrent (forkIO, threadDelay) +import Control.Concurrent.STM +import Control.Monad import Data.Time.Clock (getCurrentTime) import Data.Time.LocalTime (getCurrentTimeZone) import Server -import Simplex.Chat.Controller (currentRemoteHost, versionNumber, versionString) +import Simplex.Chat.Controller (ChatController (..), ChatResponse (..), currentRemoteHost, versionNumber, versionString) import Simplex.Chat.Core import Simplex.Chat.Options import Simplex.Chat.Terminal @@ -22,20 +24,28 @@ main = do opts@ChatOpts {chatCmd, chatServerPort} <- getChatOpts appDir "simplex_v1" if null chatCmd then case chatServerPort of - Just chatPort -> - simplexChatServer defaultChatServerConfig {chatPort} terminalChatConfig opts - _ -> do - welcome opts - t <- withTerminal pure - simplexChatTerminal terminalChatConfig opts t - else simplexChatCore terminalChatConfig opts $ \user cc -> do - rh <- readTVarIO $ currentRemoteHost cc - let cmdRH = rh -- response RemoteHost is the same as for the command itself - r <- sendChatCmdStr cc chatCmd - ts <- getCurrentTime - tz <- getCurrentTimeZone - putStrLn $ serializeChatResponse (rh, Just user) ts tz cmdRH r - threadDelay $ chatCmdDelay opts * 1000000 + Just chatPort -> simplexChatServer defaultChatServerConfig {chatPort} terminalChatConfig opts + _ -> runCLI opts + else simplexChatCore terminalChatConfig opts $ runCommand opts + where + runCLI opts = do + welcome opts + t <- withTerminal pure + simplexChatTerminal terminalChatConfig opts t + runCommand ChatOpts {chatCmd, chatCmdLog, chatCmdDelay} user cc = do + when (chatCmdLog /= CCLNone) . void . forkIO . forever $ do + (_, _, r') <- atomically . readTBQueue $ outputQ cc + case r' of + CRNewChatItem {} -> printResponse r' + _ -> when (chatCmdLog == CCLAll) $ printResponse r' + sendChatCmdStr cc chatCmd >>= printResponse + threadDelay $ chatCmdDelay * 1000000 + where + printResponse r = do + ts <- getCurrentTime + tz <- getCurrentTimeZone + rh <- readTVarIO $ currentRemoteHost cc + putStrLn $ serializeChatResponse (rh, Just user) ts tz rh r welcome :: ChatOpts -> IO () welcome ChatOpts {coreOptions = CoreChatOpts {dbFilePrefix, networkConfig}} = diff --git a/apps/simplex-directory-service/src/Directory/Options.hs b/apps/simplex-directory-service/src/Directory/Options.hs index 6d4e1296f2..78157d7e11 100644 --- a/apps/simplex-directory-service/src/Directory/Options.hs +++ b/apps/simplex-directory-service/src/Directory/Options.hs @@ -14,7 +14,7 @@ where import Options.Applicative import Simplex.Chat.Bot.KnownContacts import Simplex.Chat.Controller (updateStr, versionNumber, versionString) -import Simplex.Chat.Options (ChatOpts (..), CoreChatOpts, coreChatOptsP) +import Simplex.Chat.Options (ChatOpts (..), ChatCmdLog (..), CoreChatOpts, coreChatOptsP) data DirectoryOpts = DirectoryOpts { coreOptions :: CoreChatOpts, @@ -77,6 +77,7 @@ mkChatOpts DirectoryOpts {coreOptions} = deviceName = Nothing, chatCmd = "", chatCmdDelay = 3, + chatCmdLog = CCLNone, chatServerPort = Nothing, optFilesFolder = Nothing, showReactions = False, diff --git a/blog/20240124-simplex-chat-infrastructure-costs-v5-5-simplex-ux-private-notes-group-history.md b/blog/20240124-simplex-chat-infrastructure-costs-v5-5-simplex-ux-private-notes-group-history.md new file mode 100644 index 0000000000..43c502d8c4 --- /dev/null +++ b/blog/20240124-simplex-chat-infrastructure-costs-v5-5-simplex-ux-private-notes-group-history.md @@ -0,0 +1,119 @@ +--- +layout: layouts/article.html +title: "SimpleX Chat: free infrastructure from Linode, v5.5 released with private notes, group history and a simpler UX to connect." +date: 2024-01-24 +previewBody: blog_previews/20240124.html +image: images/20240124-connect1.png +permalink: "/blog/20240124-simplex-chat-infrastructure-costs-v5-5-simplex-ux-private-notes-group-history.html" +--- + +# SimpleX Chat: free infrastructure from Linode, v5.5 released with private notes, group history and a simpler UX to connect. + +**Published:** Jan 24, 2024 + +[SimpleX Chat infrastructure on Linode](#simplex-chat-infrastructure-on-linode): +- Free infrastructure. +- SimpleX servers in Linode Marketplace. +- High capacity messaging servers. + +What's new in v5.5: +- [private notes](#private-notes) +- [group history](#group-history) +- [simpler UX to connect to other users](#simpler-ux-to-connect-to-other-users) +- [message delivery stability and other improvements](#message-delivery-stability-and-other-improvements) + +Also, we added Hungarian (only Android) and Turkish interface languages, thanks to [our users and Weblate](https://github.com/simplex-chat/simplex-chat#help-translating-simplex-chat). + +SimpleX Chat Android app is now available in 20 languages! + +## SimpleX Chat infrastructure on Linode + +We chose Linode as our hosting provider as and they have been consistently reliable, cheaper than alternatives, with excellent support and great documentation. + +When Linode was acquired by Akamai, we were a bit nervous about how it may affect service quality. So far it's been working out quite well. + +As the usage of SimpleX network was growing, so did our hosting costs, and from being really small they started to become significant, particularly as we didn't yet manage to optimize the servers last year. + +Linode helped - we're really excited to announce that Akamai decided to support SimpleX Chat growth by accepting it into their [Linode Rise startup program](https://www.linode.com/linode-for-startups/). + +Thanks to this program: + +- we received free infrastructure for the first year up to $10,000 per month, no strings attached. It already saved us some money, and gave us enough time to optimize the servers - the latest version of the servers are much less costly to operate with the current traffic, and can support a much larger traffic within this limit. In the year 2 of the program we will receive 50% discount with unlimited traffic, and in year 3 - 25% discount. + +- Linode Marketplace now includes [SimpleX Chat messages and file servers](https://www.linode.com/marketplace/apps/simplex-chat/simplex-chat/) - you can get free $100 credits for the first 2 months and run your own servers in just a few clicks, and use them in SimpleX Chat apps. Anybody can submit their application to Linode marketplace, but dedicated support we have from Linode team via this program made it simpler. + +- Akamai solution engineers are helping us to design high capacity server solution, free of charge, so that a single host can provide horizontally scalable capacity for messaging, allowing for a much larger number of concurrent users on a single server address. Initially we considered using HAProxy, and the latest proof of concept uses OpenResty - a fork of Nginx with Lua script engine - to route requests from a single host to multiple SMP relays, reducing an overhead for the clients that would be configured with a smaller number of higher capacity servers. This project is still in progress, there will be more details as we roll it out. + +## What's new in v5.5 + +### Private notes + +<img src="./images/20240124-notes1.png" width="220" class="float-to-left"> <img src="./images/20240124-notes2.png" width="220" class="float-to-left"> + +*"Where do I put notes for myself?"* was a very common support question. There was a workaround - you could create an empty group, just with yourself, and use it to save notes, but it was not very convenient, and you could accidentally add members there. + +This version has a more convenient and private alternative - the Private notes. It looks like an ordinary conversation where you can put text messages, links with previews, and any media and files, but they are not sent anywhere - they are stored locally, only on your device, with encrypted files. + +You can access the Private notes created in mobile app from desktop app too, by linking a mobile and desktop apps - the feature [added in the previous version](./20231125-simplex-chat-v5-4-link-mobile-desktop-quantum-resistant-better-groups.md). It allows to conveniently share files between the devices without sending them over the Internet. + +### Group history + +<img src="./images/20240124-history1.png" width="220" class="float-to-left"> <img src="./images/20240124-history2.png" width="220" class="float-to-left"> + +In the previous version, when users joined groups, they only saw an empty conversation, and the notifications of being connected to other members. This version allows group admins sending recent group history to the new members - this option is enabled by default for new groups, and can be enabled for the existing groups in the preferences. So now new members can join the conversation as soon as they join. + +This does not mean that these messages are stored on any servers - the admin member that adds a new member to the group sends these messages directly when a new member joins. Groups are still fully decentralized, do not have any identity on the network, and fully private - only their members know they exist. + +That is, unless a group owner decides to make it public. Groups can be registered in [SimpleX groups directory](https://simplex.chat/contact#/?v=1-4&smp=smp%3A%2F%2Fu2dS9sG8nMNURyZwqASV4yROM28Er0luVTx5X1CsMrU%3D%40smp4.simplex.im%2FeXSPwqTkKyDO3px4fLf1wx3MvPdjdLW3%23%2F%3Fv%3D1-2%26dh%3DMCowBQYDK2VuAyEAaiv6MkMH44L2TcYrt_CsX3ZvM11WgbMEUn0hkIKTOho%253D%26srv%3Do5vmywmrnaxalvz6wi3zicyftgio6psuvyniis6gco6bp6ekl4cqj4id.onion) to be discovered by the new members - group directory is also improved. + +### Simpler UX to connect to other users + +<img src="./images/20240124-connect1.png" width="220" class="float-to-left"> <img src="./images/20240124-connect2.png" width="220" class="float-to-left"> + +SimpleX platform has no user accounts or identities, and while it improves metadata privacy, it also makes it harder to understand how to connect to other people, particularly for the new users who are not invited by the existing users. + +This version simplifies this interface by allowing to connect via the received link just by pasting the address into the search bar, as is common in many wallet apps and some other decentralized messengers. We also improved the interface of creating invitation links. + +We will continue working on improving and simplifying user interface throughout the year. Please send us any feedback and suggestions to the team's address available in the app. + +### Message delivery stability and other improvements + +One of the long standing issues was that message reception could get stuck in some rare occasions, and only get resumed once the app is fully restarted. As Android app includes an always-on notification service that runs in background, full restart should be done via the app settings. + +This version fixed many issues with message delivery stability and also added some diagnostics to identify any other cases when message delivery may stop. These fixes should also reduce battery usage, particularly on slow internet connections. + +Other improvements in this version: +- you can now reveal secret messages by tapping. To send a secret message wrap in "#" characters, e.g. "\#password\#". +- you can delete the last user profile, simplifying account deletion. If you have [hidden user profiles](./20230328-simplex-chat-v4-6-hidden-profiles.md), they won't be deleted in this case, and will be accessible again once you create a new profile. + +## SimpleX platform + +Some links to answer the most common questions: + +[How can SimpleX deliver messages without user identifiers](./20220511-simplex-chat-v2-images-files.md#the-first-messaging-platform-without-user-identifiers). + +[What are the risks to have identifiers assigned to the users](./20220711-simplex-chat-v3-released-ios-notifications-audio-video-calls-database-export-import-protocol-improvements.md#why-having-users-identifiers-is-bad-for-the-users). + +[Technical details and limitations](https://github.com/simplex-chat/simplex-chat#privacy-technical-details-and-limitations). + +[How SimpleX is different from Session, Matrix, Signal, etc.](https://github.com/simplex-chat/simplex-chat/blob/stable/README.md#frequently-asked-questions). + +Please also see our [website](https://simplex.chat). + +## Help us with donations + +Huge thank you to everybody who donated to SimpleX Chat! + +We are prioritizing users privacy and security - it would be impossible without your support. + +Our pledge to our users is that SimpleX protocols are and will remain open, and in public domain, - so anybody can build the future implementations of the clients and the servers. We are building SimpleX platform based on the same principles as email and web, but much more private and secure. + +Your donations help us raise more funds – any amount, even the price of the cup of coffee, makes a big difference for us. + +See [this section](https://github.com/simplex-chat/simplex-chat/tree/master#help-us-with-donations) for the ways to donate. + +Thank you, + +Evgeny + +SimpleX Chat founder diff --git a/blog/README.md b/blog/README.md index 815009139f..3afa61eeff 100644 --- a/blog/README.md +++ b/blog/README.md @@ -1,5 +1,20 @@ # Blog +Jan 24, 2024 [SimpleX Chat: free infrastructure from Linode, v5.5 released](./20240124-simplex-chat-infrastructure-costs-v5-5-simplex-ux-private-notes-group-history.md) + +SimpleX Chat infrastructure on Linode: +- Free infrastructure. +- SimpleX servers in Linode Marketplace. +- High capacity messaging servers. + +What's new in v5.5: +- private notes. +- group history. +- simpler UX to connect to other users. +- message delivery stability and other improvements. + +--- + Nov 25, 2023 [SimpleX Chat v5.4 released](./20231125-simplex-chat-v5-4-link-mobile-desktop-quantum-resistant-better-groups.md) - Link mobile and desktop apps via secure quantum-resistant protocol. 🔗 diff --git a/blog/images/20240124-connect1.png b/blog/images/20240124-connect1.png new file mode 100644 index 0000000000..9b5a3cd1ff Binary files /dev/null and b/blog/images/20240124-connect1.png differ diff --git a/blog/images/20240124-connect2.png b/blog/images/20240124-connect2.png new file mode 100644 index 0000000000..fda81efb20 Binary files /dev/null and b/blog/images/20240124-connect2.png differ diff --git a/blog/images/20240124-history1.png b/blog/images/20240124-history1.png new file mode 100644 index 0000000000..fbba77b5fa Binary files /dev/null and b/blog/images/20240124-history1.png differ diff --git a/blog/images/20240124-history2.png b/blog/images/20240124-history2.png new file mode 100644 index 0000000000..a54992bb48 Binary files /dev/null and b/blog/images/20240124-history2.png differ diff --git a/blog/images/20240124-notes1.png b/blog/images/20240124-notes1.png new file mode 100644 index 0000000000..4c253b4704 Binary files /dev/null and b/blog/images/20240124-notes1.png differ diff --git a/blog/images/20240124-notes2.png b/blog/images/20240124-notes2.png new file mode 100644 index 0000000000..82c6b18eb5 Binary files /dev/null and b/blog/images/20240124-notes2.png differ diff --git a/cabal.project b/cabal.project index afee4d3994..0c6105ab2b 100644 --- a/cabal.project +++ b/cabal.project @@ -2,8 +2,6 @@ packages: . -- packages: . ../simplexmq -- packages: . ../simplexmq ../direct-sqlcipher ../sqlcipher-simple -with-compiler: ghc-8.10.7 - index-state: 2023-12-12T00:00:00Z package cryptostore @@ -14,7 +12,7 @@ constraints: zip +disable-bzip2 +disable-zstd source-repository-package type: git location: https://github.com/simplex-chat/simplexmq.git - tag: f6ed4640d407f8879273d104a3e69069806dcb7c + tag: 7a0cd8041bbb7d7ab2f089395a244dc4af0f9e3b source-repository-package type: git diff --git a/docs/DOWNLOADS.md b/docs/DOWNLOADS.md index 5362e4f2c3..0429731761 100644 --- a/docs/DOWNLOADS.md +++ b/docs/DOWNLOADS.md @@ -7,7 +7,7 @@ revision: 25.11.2023 | Updated 25.11.2023 | Languages: EN | # Download SimpleX apps -The latest stable version is v5.4.1. +The latest stable version is v5.5. You can get the latest beta releases from [GitHub](https://github.com/simplex-chat/simplex-chat/releases). @@ -21,24 +21,24 @@ You can get the latest beta releases from [GitHub](https://github.com/simplex-ch Using the same profile as on mobile device is not yet supported – you need to create a separate profile to use desktop apps. -**Linux**: [AppImage](https://github.com/simplex-chat/simplex-chat/releases/download/v5.4.1/simplex-desktop-x86_64.AppImage) (most Linux distros), [Ubuntu 20.04](https://github.com/simplex-chat/simplex-chat/releases/download/v5.4.1/simplex-desktop-ubuntu-20_04-x86_64.deb) (and Debian-based distros), [Ubuntu 22.04](https://github.com/simplex-chat/simplex-chat/releases/download/v5.4.1/simplex-desktop-ubuntu-22_04-x86_64.deb). +**Linux**: [AppImage](https://github.com/simplex-chat/simplex-chat/releases/download/v5.5.0/simplex-desktop-x86_64.AppImage) (most Linux distros), [Ubuntu 20.04](https://github.com/simplex-chat/simplex-chat/releases/download/v5.5.0/simplex-desktop-ubuntu-20_04-x86_64.deb) (and Debian-based distros), [Ubuntu 22.04](https://github.com/simplex-chat/simplex-chat/releases/download/v5.5.0/simplex-desktop-ubuntu-22_04-x86_64.deb). -**Mac**: [x86_64](https://github.com/simplex-chat/simplex-chat/releases/download/v5.4.1/simplex-desktop-macos-x86_64.dmg) (Intel), [aarch64](https://github.com/simplex-chat/simplex-chat/releases/download/v5.4.1/simplex-desktop-macos-aarch64.dmg) (Apple Silicon). +**Mac**: [x86_64](https://github.com/simplex-chat/simplex-chat/releases/download/v5.5.0/simplex-desktop-macos-x86_64.dmg) (Intel), [aarch64](https://github.com/simplex-chat/simplex-chat/releases/download/v5.5.0/simplex-desktop-macos-aarch64.dmg) (Apple Silicon). -**Windows**: [x86_64](https://github.com/simplex-chat/simplex-chat/releases/download/v5.4.1/simplex-desktop-windows-x86_64.msi). +**Windows**: [x86_64](https://github.com/simplex-chat/simplex-chat/releases/download/v5.5.0/simplex-desktop-windows-x86_64.msi). ## Mobile apps **iOS**: [App store](https://apps.apple.com/us/app/simplex-chat/id1605771084), [TestFlight](https://testflight.apple.com/join/DWuT2LQu). -**Android**: [Play store](https://play.google.com/store/apps/details?id=chat.simplex.app), [F-Droid](https://simplex.chat/fdroid/), [APK aarch64](https://github.com/simplex-chat/simplex-chat/releases/download/v5.4.1/simplex.apk), [APK armv7](https://github.com/simplex-chat/simplex-chat/releases/download/v5.4.1/simplex-armv7a.apk). +**Android**: [Play store](https://play.google.com/store/apps/details?id=chat.simplex.app), [F-Droid](https://simplex.chat/fdroid/), [APK aarch64](https://github.com/simplex-chat/simplex-chat/releases/download/v5.5.0/simplex.apk), [APK armv7](https://github.com/simplex-chat/simplex-chat/releases/download/v5.5.0/simplex-armv7a.apk). ## Terminal (console) app See [Using terminal app](/docs/CLI.md). -**Linux**: [Ubuntu 20.04](https://github.com/simplex-chat/simplex-chat/releases/download/v5.4.1/simplex-chat-ubuntu-20_04-x86-64), [Ubuntu 22.04](https://github.com/simplex-chat/simplex-chat/releases/download/v5.4.1/simplex-chat-ubuntu-22_04-x86-64). +**Linux**: [Ubuntu 20.04](https://github.com/simplex-chat/simplex-chat/releases/download/v5.5.0/simplex-chat-ubuntu-20_04-x86-64), [Ubuntu 22.04](https://github.com/simplex-chat/simplex-chat/releases/download/v5.5.0/simplex-chat-ubuntu-22_04-x86-64). -**Mac** [x86_64](https://github.com/simplex-chat/simplex-chat/releases/download/v5.4.1/simplex-chat-macos-x86-64), aarch64 - [compile from source](./CLI.md#). +**Mac** [x86_64](https://github.com/simplex-chat/simplex-chat/releases/download/v5.5.0/simplex-chat-macos-x86-64), aarch64 - [compile from source](/docs/CLI.md#). -**Windows**: [x86_64](https://github.com/simplex-chat/simplex-chat/releases/download/v5.4.1/simplex-chat-windows-x86-64). +**Windows**: [x86_64](https://github.com/simplex-chat/simplex-chat/releases/download/v5.5.0/simplex-chat-windows-x86-64). diff --git a/docs/rfcs/2024-01-04-members-profile-update.md b/docs/rfcs/2024-01-04-members-profile-update.md new file mode 100644 index 0000000000..c91cbcabab --- /dev/null +++ b/docs/rfcs/2024-01-04-members-profile-update.md @@ -0,0 +1,50 @@ +# Sending profile update to group members + +## Problem + +Profile updates are only sent to direct contacts, as sending them to all group member connections is prohibitively expensive. This results in group members not receiving profile updates. Previously the issue was less acute as all group members were created with two sets of connections, one being used as direct connection for their respective contacts (though the traffic issue was more pronounced due to that); also contacts were merged across group members. Since client started to support deletion of group member contact records, and later stopped creating direct connections for group members altogether, it became less likely for group members to receive profile updates. Still even in the latest versions group members can receive profile updates after creating direct contacts via "Send direct message" button, or connecting out-of-band and merging contact and member records. + +## Solution + +Keep track of which members received latest profile updates. Send profile updates when user is active in group. + +### How to track + +- users.user_member_profile_updated_at +- group_members.user_member_profile_sent_at +- when user updates profile, remember new user_member_profile_updated_at, later to be compared against group_members.user_member_profile_sent_at + +### What to track + +- not all profile fields make sense to send in profile update to group members +- changes to displayName, fullName, image should be sent +- changes to preferences aren't necessary to send as they only apply to user contacts +- changes to contactLink may be sent, but can also be excluded for purposes of privacy + - some users don't expect that sharing address (contactLink) shares it not only with contacts, but also group members + - this is a broader issue, as the user's contact link may also be sent in user's profile by admin when introducing members - it makes sense to either ignore this for the purposes of this feature, of change it in group handshake as well +- it then makes sense to remember new timestamp on user record only if name or image is changed + +### When/To whom to send + +- when user is active in group (i.e. broadcasts message via sendGroupMessage), compare group_members.user_member_profile_sent_at against users.user_member_profile_updated_at to determine whether latest profile update wasn't yet sent +- don't send to members in groups where user is incognito +- don't send to members with whom user has direct contact (as it would overwrite full profile update sent to contact)? + - alternatively it may be better to send the same pruned profile to such members, and for them to ignore this update (or only apply name and image updates, in case sender has silently deleted them as contact without notifying?): + - this would ensure that they do receive it in case they silently deleted contact without notifying user + - it simplifies processing, as then the same message is sent to all group members + - may remember "profile update hashes" on receiving side to not apply profile updates received via member connection to contact profile, if they arrive after previously processed updates received via contact connection (e.g. update that was received late would overwrite more up-to-date updates received via contact connection, until following messages arrive) +- it seems unnecessary to send profile updates on service messages to individual members: + - it would otherwise lead to members having different profiles of user at different points in time + - not all of these messages create chat items anyway (forward, intro messages), so user name/image wouldn't matter + - most if not all of these messages are sent by admins, who are likely to send either some content messages, group updates, or announce new members (x.grp.mem.new, which is also broadcasted) + - it simplifies processing, as then profile update is sent to all current members +- considering above points, perhaps we can simplify to track user_member_profile_sent_at on groups instead of group_members + - group_members.user_member_profile_sent_at -> groups.user_member_profile_sent_at + +### How to send + +Two options: +- send as a separate message, don't special case +- send batched with the main message (using chat protocol batching mechanism), it would avoid broadcasting additional message for users without profile images, and likely in some cases (when main message is short) even with them + - conflicts with forwarding as forwarding of batched messages is not supported + - simply implementing forwarding of batched messages is not enough, because currently there is no way to differentiate between history and other batched messages (and received history shouldn't be forwarded) diff --git a/libsimplex.dll.def b/libsimplex.dll.def index 4255f4409c..f927e3ee24 100644 --- a/libsimplex.dll.def +++ b/libsimplex.dll.def @@ -3,6 +3,7 @@ EXPORTS hs_init hs_init_with_rtsopts chat_migrate_init + chat_close_store chat_send_cmd chat_send_remote_cmd chat_recv_msg diff --git a/package.yaml b/package.yaml index e42a8d3c4c..9eba9918ea 100644 --- a/package.yaml +++ b/package.yaml @@ -1,5 +1,5 @@ name: simplex-chat -version: 5.4.4.0 +version: 5.5.0.4 #synopsis: #description: homepage: https://github.com/simplex-chat/simplex-chat#readme diff --git a/scripts/android/download-libs.sh b/scripts/android/download-libs.sh index 5b9e1036fb..1691838d94 100755 --- a/scripts/android/download-libs.sh +++ b/scripts/android/download-libs.sh @@ -37,12 +37,12 @@ for ((i = 0 ; i < ${#arches[@]}; i++)); do mkdir -p "$output_dir" 2> /dev/null - curl --tlsv1.2 --location -o libsupport.zip $job_repo/$arch-android:lib:support.x86_64-linux/latest/download/1 && \ + curl --tlsv1.2 --location -o libsupport.zip $job_repo/x86_64-linux."$arch"-android:lib:support/latest/download/1 && \ unzip -o libsupport.zip && \ mv libsupport.so "$output_dir" && \ rm libsupport.zip - curl --tlsv1.2 --location -o libsimplex.zip "$job_repo"/"$arch"-android:lib:simplex-chat.x86_64-linux/latest/download/1 && \ + curl --tlsv1.2 --location -o libsimplex.zip "$job_repo"/x86_64-linux."$arch"-android:lib:simplex-chat/latest/download/1 && \ unzip -o libsimplex.zip && \ mv libsimplex.so "$output_dir" && \ rm libsimplex.zip diff --git a/scripts/ios/download-libs.sh b/scripts/ios/download-libs.sh index d0a3c9c621..6fb6576e94 100755 --- a/scripts/ios/download-libs.sh +++ b/scripts/ios/download-libs.sh @@ -35,7 +35,7 @@ for ((i = 0 ; i < ${#arches[@]}; i++)); do output_arch="${output_arches[$i]}" output_dir="$HOME/Downloads" - curl --tlsv1.2 --location -o "$output_dir"/pkg-ios-"$arch"-swift-json.zip "$job_repo"/"$arch"-darwin-ios:lib:simplex-chat."$arch"-darwin/latest/download/1 && \ + curl --tlsv1.2 --location -o "$output_dir"/pkg-ios-"$arch"-swift-json.zip "$job_repo"/"$arch"-darwin."$arch"-darwin-ios:lib:simplex-chat/latest/download/1 && \ unzip -o "$output_dir"/pkg-ios-"$output_arch"-swift-json.zip -d ~/Downloads/pkg-ios-"$output_arch"-swift-json done -sh "$root_dir"/scripts/ios/prepare-x86_64.sh +sh "$root_dir"/scripts/ios/prepare-x86_64.sh \ No newline at end of file diff --git a/scripts/ios/import-localizations.sh b/scripts/ios/import-localizations.sh index c699966d79..4bf33f7dbd 100755 --- a/scripts/ios/import-localizations.sh +++ b/scripts/ios/import-localizations.sh @@ -2,7 +2,7 @@ set -e -langs=( en bg cs de es fi fr it ja nl pl ru th uk zh-Hans ) +langs=( en bg cs de es fi fr it ja nl pl ru th tr uk zh-Hans ) for lang in "${langs[@]}"; do echo "***" diff --git a/scripts/nix/sha256map.nix b/scripts/nix/sha256map.nix index e87143582a..53bd19a368 100644 --- a/scripts/nix/sha256map.nix +++ b/scripts/nix/sha256map.nix @@ -1,5 +1,5 @@ { - "https://github.com/simplex-chat/simplexmq.git"."f6ed4640d407f8879273d104a3e69069806dcb7c" = "072rakv697f85i8ldjl7bj7jc7vfmzphasx2i4ynwgz3kksydfp5"; + "https://github.com/simplex-chat/simplexmq.git"."7a0cd8041bbb7d7ab2f089395a244dc4af0f9e3b" = "0jxf9dnsg14ffd1y3i7md2ninrds4daq1fmpnd6j5z99im07ns52"; "https://github.com/simplex-chat/hs-socks.git"."a30cc7a79a08d8108316094f8f2f82a0c5e1ac51" = "0yasvnr7g91k76mjkamvzab2kvlb1g5pspjyjn2fr6v83swjhj38"; "https://github.com/simplex-chat/direct-sqlcipher.git"."f814ee68b16a9447fbb467ccc8f29bdd3546bfd9" = "1ql13f4kfwkbaq7nygkxgw84213i0zm7c1a8hwvramayxl38dq5d"; "https://github.com/simplex-chat/sqlcipher-simple.git"."a46bd361a19376c5211f1058908fc0ae6bf42446" = "1z0r78d8f0812kxbgsm735qf6xx8lvaz27k1a0b4a2m0sshpd5gl"; diff --git a/simplex-chat.cabal b/simplex-chat.cabal index 2667f700fa..b1fd924ae5 100644 --- a/simplex-chat.cabal +++ b/simplex-chat.cabal @@ -5,7 +5,7 @@ cabal-version: 1.12 -- see: https://github.com/sol/hpack name: simplex-chat -version: 5.4.4.0 +version: 5.5.0.4 category: Web, System, Services, Cryptography homepage: https://github.com/simplex-chat/simplex-chat#readme author: simplex.chat @@ -129,6 +129,10 @@ library Simplex.Chat.Migrations.M20231207_chat_list_pagination Simplex.Chat.Migrations.M20231214_item_content_tag Simplex.Chat.Migrations.M20231215_recreate_msg_deliveries + Simplex.Chat.Migrations.M20240102_note_folders + Simplex.Chat.Migrations.M20240104_members_profile_update + Simplex.Chat.Migrations.M20240115_block_member_for_all + Simplex.Chat.Migrations.M20240122_indexes Simplex.Chat.Mobile Simplex.Chat.Mobile.File Simplex.Chat.Mobile.Shared @@ -150,6 +154,7 @@ library Simplex.Chat.Store.Groups Simplex.Chat.Store.Messages Simplex.Chat.Store.Migrations + Simplex.Chat.Store.NoteFolders Simplex.Chat.Store.Profiles Simplex.Chat.Store.Remote Simplex.Chat.Store.Shared @@ -541,6 +546,7 @@ test-suite simplex-chat-test ChatTests.Direct ChatTests.Files ChatTests.Groups + ChatTests.Local ChatTests.Profiles ChatTests.Utils JSONTests diff --git a/src/.hspec b/src/.hspec new file mode 100644 index 0000000000..28f079001c --- /dev/null +++ b/src/.hspec @@ -0,0 +1 @@ +--times diff --git a/src/Simplex/Chat.hs b/src/Simplex/Chat.hs index 9e813b55bc..564db9b42c 100644 --- a/src/Simplex/Chat.hs +++ b/src/Simplex/Chat.hs @@ -24,7 +24,7 @@ import Control.Monad.Reader import qualified Data.Aeson as J import Data.Attoparsec.ByteString.Char8 (Parser) import qualified Data.Attoparsec.ByteString.Char8 as A -import Data.Bifunctor (bimap, first) +import Data.Bifunctor (bimap, first, second) import Data.ByteArray (ScrubbedBytes) import qualified Data.ByteArray as BA import qualified Data.ByteString.Base64 as B64 @@ -36,6 +36,7 @@ import Data.Constraint (Dict (..)) import Data.Either (fromRight, lefts, partitionEithers, rights) import Data.Fixed (div') import Data.Functor (($>)) +import Data.Functor.Identity import Data.Int (Int64) import Data.List (find, foldl', isSuffixOf, partition, sortOn) import Data.List.NonEmpty (NonEmpty (..), nonEmpty, toList, (<|)) @@ -71,6 +72,7 @@ import Simplex.Chat.Store.Direct import Simplex.Chat.Store.Files import Simplex.Chat.Store.Groups import Simplex.Chat.Store.Messages +import Simplex.Chat.Store.NoteFolders import Simplex.Chat.Store.Profiles import Simplex.Chat.Store.Shared import Simplex.Chat.Types @@ -82,10 +84,11 @@ import Simplex.FileTransfer.Client.Presets (defaultXFTPServers) import Simplex.FileTransfer.Description (ValidFileDescription, gb, kb, mb) import Simplex.FileTransfer.Protocol (FileParty (..), FilePartyI) import Simplex.Messaging.Agent as Agent -import Simplex.Messaging.Agent.Client (AgentStatsKey (..), SubInfo (..), agentClientStore, temporaryAgentError) +import Simplex.Messaging.Agent.Client (AgentStatsKey (..), SubInfo (..), agentClientStore, getAgentWorkersDetails, getAgentWorkersSummary, temporaryAgentError) import Simplex.Messaging.Agent.Env.SQLite (AgentConfig (..), InitialAgentServers (..), createAgentStore, defaultAgentConfig) import Simplex.Messaging.Agent.Lock import Simplex.Messaging.Agent.Protocol +import qualified Simplex.Messaging.Agent.Protocol as AP (AgentErrorType (..)) import Simplex.Messaging.Agent.Store.SQLite (MigrationConfirmation (..), MigrationError, SQLiteStore (dbNew), execSQL, upMigration, withConnection) import Simplex.Messaging.Agent.Store.SQLite.DB (SlowQueryStats (..)) import qualified Simplex.Messaging.Agent.Store.SQLite.DB as DB @@ -105,9 +108,9 @@ import Simplex.Messaging.Util import Simplex.Messaging.Version import Simplex.RemoteControl.Invitation (RCInvitation (..), RCSignedInvitation (..)) import Simplex.RemoteControl.Types (RCCtrlAddress (..)) -import System.Exit (ExitCode, exitFailure, exitSuccess) +import System.Exit (ExitCode, exitSuccess) import System.FilePath (takeFileName, (</>)) -import System.IO (Handle, IOMode (..), SeekMode (..), hFlush, stdout) +import System.IO (Handle, IOMode (..), SeekMode (..), hFlush) import System.Random (randomRIO) import Text.Read (readMaybe) import UnliftIO.Async @@ -159,14 +162,12 @@ defaultChatConfig = _defaultSMPServers :: NonEmpty SMPServerWithAuth _defaultSMPServers = L.fromList - [ "smp://1OwYGt-yqOfe2IyVHhxz3ohqo3aCCMjtB-8wn4X_aoY=@smp11.simplex.im,6ioorbm6i3yxmuoezrhjk6f6qgkc4syabh7m3so74xunb5nzr4pwgfqd.onion", + [ "smp://0YuTwO05YJWS8rkjn9eLJDjQhFKvIYd8d4xG8X1blIU=@smp8.simplex.im,beccx4yfxxbvyhqypaavemqurytl6hozr47wfc7uuecacjqdvwpw2xid.onion", + "smp://SkIkI6EPd2D63F4xFKfHk7I1UGZVNn6k1QWZ5rcyr6w=@smp9.simplex.im,jssqzccmrcws6bhmn77vgmhfjmhwlyr3u7puw4erkyoosywgl67slqqd.onion", + "smp://6iIcWT_dF2zN_w5xzZEY7HI2Prbh3ldP07YTyDexPjE=@smp10.simplex.im,rb2pbttocvnbrngnwziclp2f4ckjq65kebafws6g4hy22cdaiv5dwjqd.onion", + "smp://1OwYGt-yqOfe2IyVHhxz3ohqo3aCCMjtB-8wn4X_aoY=@smp11.simplex.im,6ioorbm6i3yxmuoezrhjk6f6qgkc4syabh7m3so74xunb5nzr4pwgfqd.onion", "smp://UkMFNAXLXeAAe0beCa4w6X_zp18PwxSaSjY17BKUGXQ=@smp12.simplex.im,ie42b5weq7zdkghocs3mgxdjeuycheeqqmksntj57rmejagmg4eor5yd.onion", - "smp://enEkec4hlR3UtKx2NMpOUK_K4ZuDxjWBO1d9Y4YXVaA=@smp14.simplex.im,aspkyu2sopsnizbyfabtsicikr2s4r3ti35jogbcekhm3fsoeyjvgrid.onion", - "smp://h--vW7ZSkXPeOUpfxlFGgauQmXNFOzGoizak7Ult7cw=@smp15.simplex.im,oauu4bgijybyhczbnxtlggo6hiubahmeutaqineuyy23aojpih3dajad.onion", - "smp://hejn2gVIqNU6xjtGM3OwQeuk8ZEbDXVJXAlnSBJBWUA=@smp16.simplex.im,p3ktngodzi6qrf7w64mmde3syuzrv57y55hxabqcq3l5p6oi7yzze6qd.onion", - "smp://ZKe4uxF4Z_aLJJOEsC-Y6hSkXgQS5-oc442JQGkyP8M=@smp17.simplex.im,ogtwfxyi3h2h5weftjjpjmxclhb5ugufa5rcyrmg7j4xlch7qsr5nuqd.onion", - "smp://PtsqghzQKU83kYTlQ1VKg996dW4Cw4x_bvpKmiv8uns=@smp18.simplex.im,lyqpnwbs2zqfr45jqkncwpywpbtq7jrhxnib5qddtr6npjyezuwd3nqd.onion", - "smp://N_McQS3F9TGoh4ER0QstUf55kGnNSd-wXfNPZ7HukcM=@smp19.simplex.im,i53bbtoqhlc365k6kxzwdp5w3cdt433s7bwh3y32rcbml2vztiyyz5id.onion" + "smp://enEkec4hlR3UtKx2NMpOUK_K4ZuDxjWBO1d9Y4YXVaA=@smp14.simplex.im,aspkyu2sopsnizbyfabtsicikr2s4r3ti35jogbcekhm3fsoeyjvgrid.onion" ] _defaultNtfServers :: [NtfServer] @@ -279,8 +280,9 @@ newChatController where configServers :: DefaultAgentServers configServers = - let smp' = fromMaybe (smp (defaultServers :: DefaultAgentServers)) (nonEmpty smpServers) - xftp' = fromMaybe (xftp (defaultServers :: DefaultAgentServers)) (nonEmpty xftpServers) + let DefaultAgentServers {smp = defSmp, xftp = defXftp} = defaultServers + smp' = fromMaybe defSmp (nonEmpty smpServers) + xftp' = fromMaybe defXftp (nonEmpty xftpServers) in defaultServers {smp = smp', xftp = xftp', netCfg = networkConfig} agentServers :: ChatConfig -> IO InitialAgentServers agentServers config@ChatConfig {defaultServers = defServers@DefaultAgentServers {ntf, netCfg}} = do @@ -307,7 +309,7 @@ activeAgentServers ChatConfig {defaultServers} p = . filter (\ServerCfg {enabled} -> enabled) cfgServers :: UserProtocol p => SProtocolType p -> (DefaultAgentServers -> NonEmpty (ProtoServerWithAuth p)) -cfgServers = \case +cfgServers p DefaultAgentServers {smp, xftp} = case p of SPSMP -> smp SPXFTP -> xftp @@ -450,16 +452,15 @@ processChatCommand' vr = \case u <- asks currentUser (smp, smpServers) <- chooseServers SPSMP (xftp, xftpServers) <- chooseServers SPXFTP - auId <- - withStore' getUsers >>= \case - [] -> pure 1 - users -> do - when (any (\User {localDisplayName = n} -> n == displayName) users) $ - throwChatError (CEUserExists displayName) - withAgent (\a -> createUser a smp xftp) + users <- withStore' getUsers + forM_ users $ \User {localDisplayName = n, activeUser, viewPwdHash} -> + when (n == displayName) . throwChatError $ + if activeUser || isNothing viewPwdHash then CEUserExists displayName else CEInvalidDisplayName {displayName, validName = ""} + auId <- withAgent (\a -> createUser a smp xftp) ts <- liftIO $ getCurrentTime >>= if pastTimestamp then coupleDaysAgo else pure user <- withStore $ \db -> createUserRecordAt db (AgentUserId auId) p True ts - when (auId == 1) $ withStore (\db -> createContact db user simplexContactProfile) `catchChatError` \_ -> pure () + when (null users) $ withStore (\db -> createContact db user simplexContactProfile) `catchChatError` \_ -> pure () + withStore $ \db -> createNoteFolder db user storeServers user smpServers storeServers user xftpServers atomically . writeTVar u $ Just user @@ -468,15 +469,15 @@ processChatCommand' vr = \case chooseServers :: (ProtocolTypeI p, UserProtocol p) => SProtocolType p -> m (NonEmpty (ProtoServerWithAuth p), [ServerCfg p]) chooseServers protocol | sameServers = - asks currentUser >>= readTVarIO >>= \case - Nothing -> throwChatError CENoActiveUser - Just user -> do - servers <- withStore' (`getProtocolServers` user) - cfg <- asks config - pure (activeAgentServers cfg protocol servers, servers) + asks currentUser >>= readTVarIO >>= \case + Nothing -> throwChatError CENoActiveUser + Just user -> do + servers <- withStore' (`getProtocolServers` user) + cfg <- asks config + pure (activeAgentServers cfg protocol servers, servers) | otherwise = do - defServers <- asks $ defaultServers . config - pure (cfgServers protocol defServers, []) + defServers <- asks $ defaultServers . config + pure (cfgServers protocol defServers, []) storeServers user servers = unless (null servers) . withStore $ \db -> overwriteProtocolServers db user servers @@ -625,6 +626,9 @@ processChatCommand' vr = \case CTGroup -> do groupChat <- withStore (\db -> getGroupChat db vr user cId pagination search) pure $ CRApiChat user (AChat SCTGroup groupChat) + CTLocal -> do + localChat <- withStore (\db -> getLocalChat db user cId pagination search) + pure $ CRApiChat user (AChat SCTLocal localChat) CTContactRequest -> pure $ chatCmdError (Just user) "not implemented" CTContactConnection -> pure $ chatCmdError (Just user) "not supported" APIGetChatItems pagination search -> withUser $ \user -> do @@ -756,6 +760,7 @@ processChatCommand' vr = \case void . withStore' $ \db -> createSndGroupInlineFT db m conn ft sendMemberFileInline m conn ft sharedMsgId processMember _ = pure () + CTLocal -> pure $ chatCmdError (Just user) "not supported" CTContactRequest -> pure $ chatCmdError (Just user) "not supported" CTContactConnection -> pure $ chatCmdError (Just user) "not supported" where @@ -787,6 +792,22 @@ processChatCommand' vr = \case unzipMaybe3 :: Maybe (a, b, c) -> (Maybe a, Maybe b, Maybe c) unzipMaybe3 (Just (a, b, c)) = (Just a, Just b, Just c) unzipMaybe3 _ = (Nothing, Nothing, Nothing) + APICreateChatItem folderId (ComposedMessage file_ quotedItemId_ mc) -> withUser $ \user -> do + forM_ quotedItemId_ $ \_ -> throwError $ ChatError $ CECommandError "not supported" + nf <- withStore $ \db -> getNoteFolder db user folderId + createdAt <- liftIO getCurrentTime + let content = CISndMsgContent mc + let cd = CDLocalSnd nf + ciId <- createLocalChatItem user cd content createdAt + ciFile_ <- forM file_ $ \cf@CryptoFile {filePath, cryptoArgs} -> do + fsFilePath <- toFSFilePath filePath + fileSize <- liftIO $ CF.getFileContentsSize $ CryptoFile fsFilePath cryptoArgs + chunkSize <- asks $ fileChunkSize . config + withStore' $ \db -> do + fileId <- createLocalFile CIFSSndStored db user nf ciId createdAt cf fileSize chunkSize + pure CIFile {fileId, fileName = takeFileName filePath, fileSize, fileSource = Just cf, fileStatus = CIFSSndStored, fileProtocol = FPLocal} + let ci = mkChatItem cd ciId content ciFile_ Nothing Nothing Nothing False createdAt Nothing createdAt + pure . CRNewChatItem user $ AChatItem SCTLocal SMDSnd (LocalChat nf) ci APIUpdateChatItem (ChatRef cType chatId) itemId live mc -> withUser $ \user -> withChatLock "updateChatItem" $ case cType of CTDirect -> do ct@Contact {contactId} <- withStore $ \db -> getContact db user chatId @@ -832,6 +853,17 @@ processChatCommand' vr = \case else pure $ CRChatItemNotChanged user (AChatItem SCTGroup SMDSnd (GroupChat gInfo) ci) _ -> throwChatError CEInvalidChatItemUpdate CChatItem SMDRcv _ -> throwChatError CEInvalidChatItemUpdate + CTLocal -> do + (nf@NoteFolder {noteFolderId}, cci) <- withStore $ \db -> (,) <$> getNoteFolder db user chatId <*> getLocalChatItem db user chatId itemId + case cci of + CChatItem SMDSnd ci@ChatItem {content = CISndMsgContent oldMC} + | mc == oldMC -> pure $ CRChatItemNotChanged user (AChatItem SCTLocal SMDSnd (LocalChat nf) ci) + | otherwise -> withStore' $ \db -> do + currentTs <- getCurrentTime + addInitialAndNewCIVersions db itemId (chatItemTs' ci, oldMC) (currentTs, mc) + ci' <- updateLocalChatItem' db user noteFolderId ci (CISndMsgContent mc) + pure $ CRChatItemUpdated user (AChatItem SCTLocal SMDSnd (LocalChat nf) ci') + _ -> throwChatError CEInvalidChatItemUpdate CTContactRequest -> pure $ chatCmdError (Just user) "not supported" CTContactConnection -> pure $ chatCmdError (Just user) "not supported" APIDeleteChatItem (ChatRef cType chatId) itemId mode -> withUser $ \user -> withChatLock "deleteChatItem" $ case cType of @@ -856,6 +888,9 @@ processChatCommand' vr = \case (SndMessage {msgId}, _) <- sendGroupMessage user gInfo ms $ XMsgDel itemSharedMId Nothing delGroupChatItem user gInfo ci msgId Nothing (CIDMBroadcast, _, _, _) -> throwChatError CEInvalidChatItemDelete + CTLocal -> do + (nf, CChatItem _ ci) <- withStore $ \db -> (,) <$> getNoteFolder db user chatId <*> getLocalChatItem db user chatId itemId + deleteLocalCI user nf ci True False CTContactRequest -> pure $ chatCmdError (Just user) "not supported" CTContactConnection -> pure $ chatCmdError (Just user) "not supported" APIDeleteMemberChatItem gId mId itemId -> withUser $ \user -> withChatLock "deleteChatItem" $ do @@ -906,6 +941,7 @@ processChatCommand' vr = \case r = ACIReaction SCTGroup SMDSnd (GroupChat g) $ CIReaction CIGroupSnd ci' createdAt reaction pure $ CRChatItemReaction user add r _ -> throwChatError $ CECommandError "reaction not possible - no shared item ID" + CTLocal -> pure $ chatCmdError (Just user) "not supported" CTContactRequest -> pure $ chatCmdError (Just user) "not supported" CTContactConnection -> pure $ chatCmdError (Just user) "not supported" where @@ -937,6 +973,10 @@ processChatCommand' vr = \case startProximateTimedItemThread user (ChatRef CTGroup chatId, itemId) deleteAt withStore' $ \db -> updateGroupChatItemsRead db userId chatId fromToIds ok user + CTLocal -> do + user <- withStore $ \db -> getUserByNoteFolderId db chatId + withStore' $ \db -> updateLocalChatItemsRead db user chatId fromToIds + ok user CTContactRequest -> pure $ chatCmdError Nothing "not supported" CTContactConnection -> pure $ chatCmdError Nothing "not supported" APIChatUnread (ChatRef cType chatId) unreadChat -> withUser $ \user -> case cType of @@ -950,6 +990,11 @@ processChatCommand' vr = \case Group {groupInfo} <- getGroup db vr user chatId liftIO $ updateGroupUnreadChat db user groupInfo unreadChat ok user + CTLocal -> do + withStore $ \db -> do + nf <- getNoteFolder db user chatId + liftIO $ updateNoteFolderUnreadChat db user nf unreadChat + ok user _ -> pure $ chatCmdError (Just user) "not supported" APIDeleteChat (ChatRef cType chatId) notify -> withUser $ \user@User {userId} -> case cType of CTDirect -> do @@ -973,13 +1018,14 @@ processChatCommand' vr = \case pure $ CRContactConnectionDeleted user conn CTGroup -> do Group gInfo@GroupInfo {membership} members <- withStore $ \db -> getGroup db vr user chatId - let isOwner = memberRole (membership :: GroupMember) == GROwner + let GroupMember {memberRole = membershipMemRole} = membership + let isOwner = membershipMemRole == GROwner canDelete = isOwner || not (memberCurrent membership) unless canDelete $ throwChatError $ CEGroupUserRole gInfo GROwner filesInfo <- withStore' $ \db -> getGroupFileInfo db user gInfo withChatLock "deleteChat group" . procCmd $ do deleteFilesAndConns user filesInfo - when (memberActive membership && isOwner) . void $ sendGroupMessage user gInfo members XGrpDel + when (memberActive membership && isOwner) . void $ sendGroupMessage' user gInfo members XGrpDel deleteGroupLinkIfExists user gInfo deleteMembersConnections user members -- functions below are called in separate transactions to prevent crashes on android @@ -999,15 +1045,16 @@ processChatCommand' vr = \case delete ct | directOrUsed ct = pure [] | otherwise = - withStore' (\db -> checkContactHasGroups db user ct) >>= \case - Just _ -> pure [] - Nothing -> do - conns <- withStore' $ \db -> getContactConnections db userId ct - withStore' (\db -> setContactDeleted db user ct) - `catchChatError` (toView . CRChatError (Just user)) - pure $ map aConnId conns + withStore' (\db -> checkContactHasGroups db user ct) >>= \case + Just _ -> pure [] + Nothing -> do + conns <- withStore' $ \db -> getContactConnections db userId ct + withStore' (\db -> setContactDeleted db user ct) + `catchChatError` (toView . CRChatError (Just user)) + pure $ map aConnId conns + CTLocal -> pure $ chatCmdError (Just user) "not supported" CTContactRequest -> pure $ chatCmdError (Just user) "not supported" - APIClearChat (ChatRef cType chatId) -> withUser $ \user -> case cType of + APIClearChat (ChatRef cType chatId) -> withUser $ \user@User {userId} -> case cType of CTDirect -> do ct <- withStore $ \db -> getContact db user chatId filesInfo <- withStore' $ \db -> getContactFileInfo db user ct @@ -1022,6 +1069,14 @@ processChatCommand' vr = \case membersToDelete <- withStore' $ \db -> getGroupMembersForExpiration db user gInfo forM_ membersToDelete $ \m -> withStore' $ \db -> deleteGroupMember db user m pure $ CRChatCleared user (AChatInfo SCTGroup $ GroupChat gInfo) + CTLocal -> do + nf <- withStore $ \db -> getNoteFolder db user chatId + filesInfo <- withStore' $ \db -> getNoteFolderFileInfo db user nf + withChatLock "clearChat local" . procCmd $ do + mapM_ (deleteFile user) filesInfo + withStore' $ \db -> deleteNoteFolderFiles db userId nf + withStore' $ \db -> deleteNoteFolderCIs db user nf + pure $ CRChatCleared user (AChatInfo SCTLocal $ LocalChat nf) CTContactConnection -> pure $ chatCmdError (Just user) "not supported" CTContactRequest -> pure $ chatCmdError (Just user) "not supported" APIAcceptContact incognito connReqId -> withUser $ \_ -> withChatLock "acceptContact" $ do @@ -1233,10 +1288,8 @@ processChatCommand' vr = \case m <- withStore $ \db -> do liftIO $ updateGroupMemberSettings db user gId gMemberId settings getGroupMember db user gId gMemberId - when (memberActive m) $ - forM_ (memberConnId m) $ \connId -> do - let ntfOn = showMessages $ memberSettings m - withAgent (\a -> toggleConnectionNtfs a connId ntfOn) `catchChatError` (toView . CRChatError (Just user)) + let ntfOn = showMessages $ memberSettings m + toggleNtf user m ntfOn ok user APIContactInfo contactId -> withUser $ \user@User {userId} -> do -- [incognito] print user's incognito profile for this contact @@ -1307,8 +1360,8 @@ processChatCommand' vr = \case Just SecurityCode {securityCode} | sameVerificationCode code securityCode -> pure ct | otherwise -> do - withStore' $ \db -> setConnectionVerified db user connId Nothing - pure (ct :: Contact) {activeConn = Just $ (conn :: Connection) {connectionCode = Nothing}} + withStore' $ \db -> setConnectionVerified db user connId Nothing + pure (ct :: Contact) {activeConn = Just $ (conn :: Connection) {connectionCode = Nothing}} _ -> pure ct pure $ CRContactCode user ct' code Nothing -> throwChatError $ CEContactNotActive ct @@ -1321,8 +1374,8 @@ processChatCommand' vr = \case Just SecurityCode {securityCode} | sameVerificationCode code securityCode -> pure m | otherwise -> do - withStore' $ \db -> setConnectionVerified db user connId Nothing - pure (m :: GroupMember) {activeConn = Just $ (conn :: Connection) {connectionCode = Nothing}} + withStore' $ \db -> setConnectionVerified db user connId Nothing + pure (m :: GroupMember) {activeConn = Just $ (conn :: Connection) {connectionCode = Nothing}} _ -> pure m pure $ CRGroupMemberCode user g m' code _ -> throwChatError CEGroupMemberNotActive @@ -1354,7 +1407,10 @@ processChatCommand' vr = \case SetSendReceipts cName rcptsOn_ -> updateChatSettings cName (\cs -> cs {sendRcpts = rcptsOn_}) SetShowMemberMessages gName mName showMessages -> withUser $ \user -> do (gId, mId) <- getGroupAndMemberId user gName mName + gInfo <- withStore $ \db -> getGroupInfo db vr user gId m <- withStore $ \db -> getGroupMember db user gId mId + let GroupInfo {membership = GroupMember {memberRole = membershipRole}} = gInfo + when (membershipRole >= GRAdmin) $ throwChatError $ CECantBlockMemberForSelf gInfo m showMessages let settings = (memberSettings m) {showMessages} processChatCommand $ APISetMemberSettings gId mId settings ContactInfo cName -> withContactName cName APIContactInfo @@ -1407,7 +1463,7 @@ processChatCommand' vr = \case subMode <- chatReadVar subscriptionMode -- [incognito] generate profile to send incognitoProfile <- if incognito then Just <$> liftIO generateRandomProfile else pure Nothing - let profileToSend = userProfileToSend user incognitoProfile Nothing + let profileToSend = userProfileToSend user incognitoProfile Nothing False dm <- directMessage $ XInfo profileToSend connId <- withAgent $ \a -> joinConnection a (aUserId user) True cReq dm subMode conn <- withStore' $ \db -> createDirectConnection db user connId cReq ConnJoined (incognitoProfile $> profileToSend) subMode @@ -1508,6 +1564,11 @@ processChatCommand' vr = \case gId <- withStore $ \db -> getGroupIdByName db user name let chatRef = ChatRef CTGroup gId processChatCommand . APISendMessage chatRef False Nothing $ ComposedMessage Nothing Nothing mc + CTLocal + | name == "" -> do + folderId <- withStore (`getUserNoteFolderId` user) + processChatCommand . APICreateChatItem folderId $ ComposedMessage Nothing Nothing mc + | otherwise -> throwChatError $ CECommandError "not supported" _ -> throwChatError $ CECommandError "not supported" SendMemberContactMessage gName mName msg -> withUser $ \user -> do (gId, mId) <- getGroupAndMemberId user gName mName @@ -1601,12 +1662,12 @@ processChatCommand' vr = \case pure $ CRSentGroupInvitation user gInfo contact member Just member@GroupMember {groupMemberId, memberStatus, memberRole = mRole} | memberStatus == GSMemInvited -> do - unless (mRole == memRole) $ withStore' $ \db -> updateGroupMemberRole db user member memRole - withStore' (\db -> getMemberInvitation db user groupMemberId) >>= \case - Just cReq -> do - sendInvitation member {memberRole = memRole} cReq - pure $ CRSentGroupInvitation user gInfo contact member {memberRole = memRole} - Nothing -> throwChatError $ CEGroupCantResendInvitation gInfo cName + unless (mRole == memRole) $ withStore' $ \db -> updateGroupMemberRole db user member memRole + withStore' (\db -> getMemberInvitation db user groupMemberId) >>= \case + Just cReq -> do + sendInvitation member {memberRole = memRole} cReq + pure $ CRSentGroupInvitation user gInfo contact member {memberRole = memRole} + Nothing -> throwChatError $ CEGroupCantResendInvitation gInfo cName | otherwise -> throwChatError $ CEGroupDuplicateMember cName APIJoinGroup groupId -> withUser $ \user@User {userId} -> do withChatLock "joinGroup" . procCmd $ do @@ -1614,11 +1675,12 @@ processChatCommand' vr = \case inv@ReceivedGroupInvitation {fromMember} <- getGroupInvitation db vr user groupId (inv,) <$> getContactViaMember db user fromMember let ReceivedGroupInvitation {fromMember, connRequest, groupInfo = g@GroupInfo {membership}} = invitation + GroupMember {memberId = membershipMemId} = membership Contact {activeConn} = ct case activeConn of Just Connection {peerChatVRange} -> do subMode <- chatReadVar subscriptionMode - dm <- directMessage $ XGrpAcpt (memberId (membership :: GroupMember)) + dm <- directMessage $ XGrpAcpt membershipMemId agentConnId <- withAgent $ \a -> joinConnection a (aUserId user) True connRequest dm subMode withStore' $ \db -> do createMemberConnection db userId fromMember agentConnId (fromJVersionRange peerChatVRange) subMode @@ -1659,6 +1721,31 @@ processChatCommand' vr = \case ci <- saveSndChatItem user (CDGroupSnd gInfo) msg (CISndGroupEvent gEvent) toView $ CRNewChatItem user (AChatItem SCTGroup SMDSnd (GroupChat gInfo) ci) pure CRMemberRoleUser {user, groupInfo = gInfo, member = m {memberRole = memRole}, fromRole = mRole, toRole = memRole} + APIBlockMemberForAll groupId memberId blocked -> withUser $ \user -> do + Group gInfo@GroupInfo {membership} members <- withStore $ \db -> getGroup db vr user groupId + when (memberId == groupMemberId' membership) $ throwChatError $ CECommandError "can't block/unblock self" + case splitMember memberId members of + Nothing -> throwChatError $ CEException "expected to find a single blocked member" + Just (bm, remainingMembers) -> do + let GroupMember {memberId = bmMemberId, memberRole = bmRole, memberProfile = bmp} = bm + assertUserGroupRole gInfo $ max GRAdmin bmRole + when (blocked == blockedByAdmin bm) $ throwChatError $ CECommandError $ if blocked then "already blocked" else "already unblocked" + withChatLock "blockForAll" . procCmd $ do + let mrs = if blocked then MRSBlocked else MRSUnrestricted + event = XGrpMemRestrict bmMemberId MemberRestrictions {restriction = mrs} + (msg, _) <- sendGroupMessage' user gInfo remainingMembers event + let ciContent = CISndGroupEvent $ SGEMemberBlocked memberId (fromLocalProfile bmp) blocked + ci <- saveSndChatItem user (CDGroupSnd gInfo) msg ciContent + toView $ CRNewChatItem user (AChatItem SCTGroup SMDSnd (GroupChat gInfo) ci) + bm' <- withStore $ \db -> do + liftIO $ updateGroupMemberBlocked db user groupId memberId mrs + getGroupMember db user groupId memberId + toggleNtf user bm' (not blocked) + pure CRMemberBlockedForAllUser {user, groupInfo = gInfo, member = bm', blocked} + where + splitMember mId ms = case break ((== mId) . groupMemberId') ms of + (_, []) -> Nothing + (ms1, bm : ms2) -> Just (bm, ms1 <> ms2) APIRemoveMember groupId memberId -> withUser $ \user -> do Group gInfo members <- withStore $ \db -> getGroup db vr user groupId case find ((== memberId) . groupMemberId') members of @@ -1681,7 +1768,7 @@ processChatCommand' vr = \case APILeaveGroup groupId -> withUser $ \user@User {userId} -> do Group gInfo@GroupInfo {membership} members <- withStore $ \db -> getGroup db vr user groupId withChatLock "leaveGroup" . procCmd $ do - (msg, _) <- sendGroupMessage user gInfo members XGrpLeave + (msg, _) <- sendGroupMessage' user gInfo members XGrpLeave ci <- saveSndChatItem user (CDGroupSnd gInfo) msg (CISndGroupEvent SGEUserLeft) toView $ CRNewChatItem user (AChatItem SCTGroup SMDSnd (GroupChat gInfo) ci) -- TODO delete direct connections that were unused @@ -1699,6 +1786,7 @@ processChatCommand' vr = \case groupId <- withStore $ \db -> getGroupIdByName db user gName processChatCommand $ APIJoinGroup groupId MemberRole gName gMemberName memRole -> withMemberName gName gMemberName $ \gId gMemberId -> APIMemberRole gId gMemberId memRole + BlockForAll gName gMemberName blocked -> withMemberName gName gMemberName $ \gId gMemberId -> APIBlockMemberForAll gId gMemberId blocked RemoveMember gName gMemberName -> withMemberName gName gMemberName APIRemoveMember LeaveGroup gName -> withUser $ \user -> do groupId <- withStore $ \db -> getGroupIdByName db user gName @@ -1770,12 +1858,12 @@ processChatCommand' vr = \case pure $ CRNewMemberContact user ct g m _ -> throwChatError CEGroupMemberNotActive APISendMemberContactInvitation contactId msgContent_ -> withUser $ \user -> do - (g, m, ct, cReq) <- withStore $ \db -> getMemberContact db vr user contactId + (g@GroupInfo {groupId}, m, ct, cReq) <- withStore $ \db -> getMemberContact db vr user contactId when (contactGrpInvSent ct) $ throwChatError $ CECommandError "x.grp.direct.inv already sent" case memberConn m of Just mConn -> do let msg = XGrpDirectInv cReq msgContent_ - (sndMsg, _) <- sendDirectMessage mConn msg (GroupId $ groupId (g :: GroupInfo)) + (sndMsg, _) <- sendDirectMessage mConn msg $ GroupId groupId withStore' $ \db -> setContactGrpInvSent db ct True let ct' = ct {contactGrpInvSent = True} forM_ msgContent_ $ \mc -> do @@ -1800,6 +1888,9 @@ processChatCommand' vr = \case quotedItemId <- withStore $ \db -> getGroupChatItemIdByText db user groupId cName quotedMsg let mc = MCText msg processChatCommand . APISendMessage (ChatRef CTGroup groupId) False Nothing $ ComposedMessage Nothing (Just quotedItemId) mc + ClearNoteFolder -> withUser $ \user -> do + folderId <- withStore (`getUserNoteFolderId` user) + processChatCommand $ APIClearChat (ChatRef CTLocal folderId) LastChats count_ -> withUser' $ \user -> do let count = fromMaybe 5000 count_ (errs, previews) <- partitionEithers <$> withStore' (\db -> getChatPreviews db vr user False (PTLast count) clqNoFilters) @@ -1835,7 +1926,9 @@ processChatCommand' vr = \case asks showLiveItems >>= atomically . (`writeTVar` on) >> ok_ SendFile chatName f -> withUser $ \user -> do chatRef <- getChatRef user chatName - processChatCommand . APISendMessage chatRef False Nothing $ ComposedMessage (Just f) Nothing (MCFile "") + case chatRef of + ChatRef CTLocal folderId -> processChatCommand . APICreateChatItem folderId $ ComposedMessage (Just f) Nothing (MCFile "") + _ -> processChatCommand . APISendMessage chatRef False Nothing $ ComposedMessage (Just f) Nothing (MCFile "") SendImage chatName f@(CryptoFile fPath _) -> withUser $ \user -> do chatRef <- getChatRef user chatName filePath <- toFSFilePath fPath @@ -1865,7 +1958,7 @@ processChatCommand' vr = \case FTSnd ftm@FileTransferMeta {xftpSndFile, cancelled} fts | cancelled -> throwChatError $ CEFileCancel fileId "file already cancelled" | not (null fts) && all fileCancelledOrCompleteSMP fts -> - throwChatError $ CEFileCancel fileId "file transfer is complete" + throwChatError $ CEFileCancel fileId "file transfer is complete" | otherwise -> do fileAgentConnIds <- cancelSndFile user ftm fts True deleteAgentConnectionsAsync user fileAgentConnIds @@ -1907,6 +2000,8 @@ processChatCommand' vr = \case FileStatus fileId -> withUser $ \user -> do ci@(AChatItem _ _ _ ChatItem {file}) <- withStore $ \db -> getChatItemByFileId db vr user fileId case file of + Just CIFile {fileProtocol = FPLocal} -> + throwChatError $ CECommandError "not supported for local files" Just CIFile {fileProtocol = FPXFTP} -> pure $ CRFileTransferStatusXFTP user ci _ -> do @@ -1968,7 +2063,8 @@ processChatCommand' vr = \case DeleteRemoteCtrl rc -> withUser_ $ deleteRemoteCtrl rc >> ok_ QuitChat -> liftIO exitSuccess ShowVersion -> do - let versionInfo = coreVersionInfo "" -- $(simplexmqCommitQ) + -- simplexmqCommitQ makes iOS builds crash m( + let versionInfo = coreVersionInfo "" chatMigrations <- map upMigration <$> withStore' (Migrations.getCurrent . DB.conn) agentMigrations <- withAgent getAgentMigrations pure $ CRVersionInfo {versionInfo, chatMigrations, agentMigrations} @@ -1976,6 +2072,8 @@ processChatCommand' vr = \case chatLockName <- atomically . tryReadTMVar =<< asks chatLock agentLocks <- withAgent debugAgentLocks pure CRDebugLocks {chatLockName, agentLocks} + GetAgentWorkers -> CRAgentWorkersSummary <$> withAgent getAgentWorkersSummary + GetAgentWorkersDetails -> CRAgentWorkersDetails <$> withAgent getAgentWorkersDetails GetAgentStats -> CRAgentStats . map stat <$> withAgent getAgentStats where stat (AgentStatsKey {host, clientTs, cmd, res}, count) = @@ -2017,6 +2115,9 @@ processChatCommand' vr = \case ChatRef cType <$> case cType of CTDirect -> withStore $ \db -> getContactIdByName db user name CTGroup -> withStore $ \db -> getGroupIdByName db user name + CTLocal + | name == "" -> withStore (`getUserNoteFolderId` user) + | otherwise -> throwChatError $ CECommandError "not supported" _ -> throwChatError $ CECommandError "not supported" checkChatStopped :: m ChatResponse -> m ChatResponse checkChatStopped a = asks agentAsync >>= readTVarIO >>= maybe a (const $ throwChatError CEChatNotStopped) @@ -2050,11 +2151,13 @@ processChatCommand' vr = \case getSentChatItemIdByText user@User {userId, localDisplayName} (ChatRef cType cId) msg = case cType of CTDirect -> withStore $ \db -> getDirectChatItemIdByText db userId cId SMDSnd msg CTGroup -> withStore $ \db -> getGroupChatItemIdByText db user cId (Just localDisplayName) msg + CTLocal -> withStore $ \db -> getLocalChatItemIdByText db user cId SMDSnd msg _ -> throwChatError $ CECommandError "not supported" getChatItemIdByText :: User -> ChatRef -> Text -> m Int64 getChatItemIdByText user (ChatRef cType cId) msg = case cType of CTDirect -> withStore $ \db -> getDirectChatItemIdByText' db user cId msg CTGroup -> withStore $ \db -> getGroupChatItemIdByText' db user cId msg + CTLocal -> withStore $ \db -> getLocalChatItemIdByText' db user cId msg _ -> throwChatError $ CECommandError "not supported" connectViaContact :: User -> IncognitoEnabled -> ConnectionRequestUri 'CMContact -> m ChatResponse connectViaContact user@User {userId} incognito cReq@(CRContactUri ConnReqUriData {crClientData}) = withChatLock "connectViaContact" $ do @@ -2068,36 +2171,36 @@ processChatCommand' vr = \case (_, xContactId_) -> procCmd $ do let randomXContactId = XContactId <$> drgRandomBytes 16 xContactId <- maybe randomXContactId pure xContactId_ - connect' Nothing cReqHash xContactId + connect' Nothing cReqHash xContactId False -- group link Just gLinkId -> withStore' (\db -> getConnReqContactXContactId db user cReqHash) >>= \case (Just _contact, _) -> procCmd $ do -- allow repeat contact request newXContactId <- XContactId <$> drgRandomBytes 16 - connect' (Just gLinkId) cReqHash newXContactId + connect' (Just gLinkId) cReqHash newXContactId True (_, xContactId_) -> procCmd $ do let randomXContactId = XContactId <$> drgRandomBytes 16 xContactId <- maybe randomXContactId pure xContactId_ - connect' (Just gLinkId) cReqHash xContactId + connect' (Just gLinkId) cReqHash xContactId True where - connect' groupLinkId cReqHash xContactId = do - (connId, incognitoProfile, subMode) <- requestContact user incognito cReq xContactId + connect' groupLinkId cReqHash xContactId inGroup = do + (connId, incognitoProfile, subMode) <- requestContact user incognito cReq xContactId inGroup conn <- withStore' $ \db -> createConnReqConnection db userId connId cReqHash xContactId incognitoProfile groupLinkId subMode pure $ CRSentInvitation user conn incognitoProfile connectContactViaAddress :: User -> IncognitoEnabled -> Contact -> ConnectionRequestUri 'CMContact -> m ChatResponse connectContactViaAddress user incognito ct cReq = withChatLock "connectViaContact" $ do newXContactId <- XContactId <$> drgRandomBytes 16 - (connId, incognitoProfile, subMode) <- requestContact user incognito cReq newXContactId + (connId, incognitoProfile, subMode) <- requestContact user incognito cReq newXContactId False let cReqHash = ConnReqUriHash . C.sha256Hash $ strEncode cReq ct' <- withStore $ \db -> createAddressContactConnection db user ct connId cReqHash newXContactId incognitoProfile subMode pure $ CRSentInvitationToContact user ct' incognitoProfile - requestContact :: User -> IncognitoEnabled -> ConnectionRequestUri 'CMContact -> XContactId -> m (ConnId, Maybe Profile, SubscriptionMode) - requestContact user incognito cReq xContactId = do + requestContact :: User -> IncognitoEnabled -> ConnectionRequestUri 'CMContact -> XContactId -> Bool -> m (ConnId, Maybe Profile, SubscriptionMode) + requestContact user incognito cReq xContactId inGroup = do -- [incognito] generate profile to send incognitoProfile <- if incognito then Just <$> liftIO generateRandomProfile else pure Nothing - let profileToSend = userProfileToSend user incognitoProfile Nothing + let profileToSend = userProfileToSend user incognitoProfile Nothing inGroup dm <- directMessage (XContact profileToSend $ Just xContactId) subMode <- chatReadVar subscriptionMode connId <- withAgent $ \a -> joinConnection a (aUserId user) True cReq dm subMode @@ -2114,7 +2217,7 @@ processChatCommand' vr = \case xftpCfg <- readTVarIO =<< asks userXFTPFileConfig fileSize <- liftIO $ CF.getFileContentsSize $ CryptoFile fsFilePath cfArgs when (fromInteger fileSize > maxFileSize) $ throwChatError $ CEFileSize f - let chunks = - ((- fileSize) `div` fileChunkSize) + let chunks = -((-fileSize) `div` fileChunkSize) fileInline = inlineFileMode mc inlineFiles chunks n fileMode = case xftpCfg of Just cfg @@ -2133,48 +2236,58 @@ processChatCommand' vr = \case updateProfile_ user@User {profile = p@LocalProfile {displayName = n}} p'@Profile {displayName = n'} updateUser | p' == fromLocalProfile p = pure $ CRUserProfileNoChange user | otherwise = do - when (n /= n') $ checkValidName n' - -- read contacts before user update to correctly merge preferences - -- [incognito] filter out contacts with whom user has incognito connections - contacts <- - filter (\ct -> contactReady ct && contactActive ct && not (contactConnIncognito ct)) - <$> withStore' (`getUserContacts` user) - user' <- updateUser - asks currentUser >>= atomically . (`writeTVar` Just user') - withChatLock "updateProfile" . procCmd $ do - ChatConfig {logLevel} <- asks config - summary <- foldM (processAndCount user' logLevel) (UserProfileUpdateSummary 0 0 0 []) contacts - pure $ CRUserProfileUpdated user' (fromLocalProfile p) p' summary + when (n /= n') $ checkValidName n' + -- read contacts before user update to correctly merge preferences + contacts <- withStore' (`getUserContacts` user) + user' <- updateUser + asks currentUser >>= atomically . (`writeTVar` Just user') + withChatLock "updateProfile" . procCmd $ do + let changedCts = foldr (addChangedProfileContact user') [] contacts + idsEvts = map ctSndMsg changedCts + msgReqs_ <- zipWith ctMsgReq changedCts <$> createSndMessages idsEvts + (errs, cts) <- partitionEithers . zipWith (second . const) changedCts <$> deliverMessagesB msgReqs_ + unless (null errs) $ toView $ CRChatErrors (Just user) errs + let changedCts' = filter (\ChangedProfileContact {ct, ct'} -> directOrUsed ct' && mergedPreferences ct' /= mergedPreferences ct) cts + createContactsSndFeatureItems user' changedCts' + let summary = + UserProfileUpdateSummary + { updateSuccesses = length cts, + updateFailures = length errs, + changedContacts = map (\ChangedProfileContact {ct'} -> ct') changedCts' + } + pure $ CRUserProfileUpdated user' (fromLocalProfile p) p' summary where - processAndCount user' ll s@UserProfileUpdateSummary {notChanged, updateSuccesses, updateFailures, changedContacts = cts} ct = do - let mergedProfile = userProfileToSend user Nothing $ Just ct - ct' = updateMergedPreferences user' ct - mergedProfile' = userProfileToSend user' Nothing $ Just ct' - if mergedProfile' == mergedProfile - then pure s {notChanged = notChanged + 1} - else - let cts' = if mergedPreferences ct == mergedPreferences ct' then cts else ct' : cts - in (notifyContact mergedProfile' ct' $> s {updateSuccesses = updateSuccesses + 1, changedContacts = cts'}) - `catchChatError` \e -> when (ll <= CLLInfo) (toView $ CRChatError (Just user) e) $> s {updateFailures = updateFailures + 1, changedContacts = cts'} + -- [incognito] filter out contacts with whom user has incognito connections + addChangedProfileContact :: User -> Contact -> [ChangedProfileContact] -> [ChangedProfileContact] + addChangedProfileContact user' ct changedCts = case contactSendConn_ ct' of + Left _ -> changedCts + Right conn + | connIncognito conn || mergedProfile' == mergedProfile -> changedCts + | otherwise -> ChangedProfileContact ct ct' mergedProfile' conn : changedCts where - notifyContact mergedProfile' ct' = do - void $ sendDirectContactMessage ct' (XInfo mergedProfile') - when (directOrUsed ct') $ createSndFeatureItems user' ct ct' + mergedProfile = userProfileToSend user Nothing (Just ct) False + ct' = updateMergedPreferences user' ct + mergedProfile' = userProfileToSend user' Nothing (Just ct') False + ctSndMsg :: ChangedProfileContact -> (ConnOrGroupId, ChatMsgEvent 'Json) + ctSndMsg ChangedProfileContact {mergedProfile', conn = Connection {connId}} = (ConnectionId connId, XInfo mergedProfile') + ctMsgReq :: ChangedProfileContact -> Either ChatError SndMessage -> Either ChatError MsgReq + ctMsgReq ChangedProfileContact {conn} = fmap $ \SndMessage {msgId, msgBody} -> + (conn, MsgFlags {notification = hasNotification XInfo_}, msgBody, msgId) updateContactPrefs :: User -> Contact -> Preferences -> m ChatResponse updateContactPrefs _ ct@Contact {activeConn = Nothing} _ = throwChatError $ CEContactNotActive ct updateContactPrefs user@User {userId} ct@Contact {activeConn = Just Connection {customUserProfileId}, userPreferences = contactUserPrefs} contactUserPrefs' | contactUserPrefs == contactUserPrefs' = pure $ CRContactPrefsUpdated user ct ct | otherwise = do - assertDirectAllowed user MDSnd ct XInfo_ - ct' <- withStore' $ \db -> updateContactUserPreferences db user ct contactUserPrefs' - incognitoProfile <- forM customUserProfileId $ \profileId -> withStore $ \db -> getProfileById db userId profileId - let mergedProfile = userProfileToSend user (fromLocalProfile <$> incognitoProfile) (Just ct) - mergedProfile' = userProfileToSend user (fromLocalProfile <$> incognitoProfile) (Just ct') - when (mergedProfile' /= mergedProfile) $ - withChatLock "updateProfile" $ do - void (sendDirectContactMessage ct' $ XInfo mergedProfile') `catchChatError` (toView . CRChatError (Just user)) - when (directOrUsed ct') $ createSndFeatureItems user ct ct' - pure $ CRContactPrefsUpdated user ct ct' + assertDirectAllowed user MDSnd ct XInfo_ + ct' <- withStore' $ \db -> updateContactUserPreferences db user ct contactUserPrefs' + incognitoProfile <- forM customUserProfileId $ \profileId -> withStore $ \db -> getProfileById db userId profileId + let mergedProfile = userProfileToSend user (fromLocalProfile <$> incognitoProfile) (Just ct) False + mergedProfile' = userProfileToSend user (fromLocalProfile <$> incognitoProfile) (Just ct') False + when (mergedProfile' /= mergedProfile) $ + withChatLock "updateProfile" $ do + void (sendDirectContactMessage ct' $ XInfo mergedProfile') `catchChatError` (toView . CRChatError (Just user)) + when (directOrUsed ct') $ createSndFeatureItems user ct ct' + pure $ CRContactPrefsUpdated user ct ct' runUpdateGroupProfile :: User -> Group -> GroupProfile -> m ChatResponse runUpdateGroupProfile user (Group g@GroupInfo {groupProfile = p@GroupProfile {displayName = n}} ms) p'@GroupProfile {displayName = n'} = do assertUserGroupRole g GROwner @@ -2189,11 +2302,13 @@ processChatCommand' vr = \case pure $ CRGroupUpdated user g g' Nothing checkValidName :: GroupName -> m () checkValidName displayName = do + when (T.null displayName) $ throwChatError CEInvalidDisplayName {displayName, validName = ""} let validName = T.pack $ mkValidName $ T.unpack displayName when (displayName /= validName) $ throwChatError CEInvalidDisplayName {displayName, validName} assertUserGroupRole :: GroupInfo -> GroupMemberRole -> m () assertUserGroupRole g@GroupInfo {membership} requiredRole = do - when (memberRole (membership :: GroupMember) < requiredRole) $ throwChatError $ CEGroupUserRole g requiredRole + let GroupMember {memberRole = membershipMemRole} = membership + when (membershipMemRole < requiredRole) $ throwChatError $ CEGroupUserRole g requiredRole when (memberStatus membership == GSMemInvited) $ throwChatError (CEGroupNotJoined g) when (memberRemoved membership) $ throwChatError CEGroupMemberUserRemoved unless (memberActive membership) $ throwChatError CEGroupMemberNotActive @@ -2219,15 +2334,15 @@ processChatCommand' vr = \case Nothing -> throwChatError CENoCurrentCall Just call@Call {contactId} | ctId == contactId -> do - call_ <- action user ct call - case call_ of - Just call' -> do - unless (isRcvInvitation call') $ withStore' $ \db -> deleteCalls db user ctId - atomically $ TM.insert ctId call' calls - _ -> do - withStore' $ \db -> deleteCalls db user ctId - atomically $ TM.delete ctId calls - ok user + call_ <- action user ct call + case call_ of + Just call' -> do + unless (isRcvInvitation call') $ withStore' $ \db -> deleteCalls db user ctId + atomically $ TM.insert ctId call' calls + _ -> do + withStore' $ \db -> deleteCalls db user ctId + atomically $ TM.delete ctId calls + ok user | otherwise -> throwChatError $ CECallContact contactId withServerProtocol :: ProtocolTypeI p => SProtocolType p -> (UserProtocol p => m a) -> m a withServerProtocol p action = case userProtocol p of @@ -2295,12 +2410,12 @@ processChatCommand' vr = \case setUserPrivacy :: User -> User -> m ChatResponse setUserPrivacy user@User {userId} user'@User {userId = userId'} | userId == userId' = do - asks currentUser >>= atomically . (`writeTVar` Just user') - withStore' (`updateUserPrivacy` user') - pure $ CRUserPrivacy {user = user', updatedUser = user'} + asks currentUser >>= atomically . (`writeTVar` Just user') + withStore' (`updateUserPrivacy` user') + pure $ CRUserPrivacy {user = user', updatedUser = user'} | otherwise = do - withStore' (`updateUserPrivacy` user') - pure $ CRUserPrivacy {user, updatedUser = user'} + withStore' (`updateUserPrivacy` user') + pure $ CRUserPrivacy {user, updatedUser = user'} checkDeleteChatUser :: User -> m () checkDeleteChatUser user@User {userId} = do users <- withStore' getUsers @@ -2329,30 +2444,28 @@ processChatCommand' vr = \case _ -> throwChatError $ CECommandError "not supported" processChatCommand $ APISetChatSettings (ChatRef cType chatId) $ updateSettings chatSettings connectPlan :: User -> AConnectionRequestUri -> m ConnectionPlan - connectPlan user (ACR SCMInvitation cReq) = do + connectPlan user (ACR SCMInvitation (CRInvitationUri crData e2e)) = do withStore' (\db -> getConnectionEntityByConnReq db vr user cReqSchemas) >>= \case Nothing -> pure $ CPInvitationLink ILPOk Just (RcvDirectMsgConnection conn ct_) -> do let Connection {connStatus, contactConnInitiated} = conn if - | connStatus == ConnNew && contactConnInitiated -> + | connStatus == ConnNew && contactConnInitiated -> pure $ CPInvitationLink ILPOwnLink - | not (connReady conn) -> + | not (connReady conn) -> pure $ CPInvitationLink (ILPConnecting ct_) - | otherwise -> case ct_ of + | otherwise -> case ct_ of Just ct -> pure $ CPInvitationLink (ILPKnown ct) Nothing -> throwChatError $ CEInternalError "ready RcvDirectMsgConnection connection should have associated contact" Just _ -> throwChatError $ CECommandError "found connection entity is not RcvDirectMsgConnection" where cReqSchemas :: (ConnReqInvitation, ConnReqInvitation) - cReqSchemas = case cReq of - (CRInvitationUri crData e2e) -> - ( CRInvitationUri crData {crScheme = CRSSimplex} e2e, - CRInvitationUri crData {crScheme = simplexChat} e2e - ) - _ -> (cReq, cReq) -- ghc8107 - connectPlan user (ACR SCMContact cReq) = do - let CRContactUri ConnReqUriData {crClientData} = cReq + cReqSchemas = + ( CRInvitationUri crData {crScheme = CRSSimplex} e2e, + CRInvitationUri crData {crScheme = simplexChat} e2e + ) + connectPlan user (ACR SCMContact (CRContactUri crData)) = do + let ConnReqUriData {crClientData} = crData groupLinkId = crClientData >>= decodeJSON >>= \(CRDataGroup gli) -> Just gli case groupLinkId of -- contact address @@ -2387,21 +2500,32 @@ processChatCommand' vr = \case (Nothing, Just _) -> throwChatError $ CECommandError "found connection entity is not RcvDirectMsgConnection" (Just gInfo@GroupInfo {membership}, _) | not (memberActive membership) && not (memberRemoved membership) -> - pure $ CPGroupLink (GLPConnectingProhibit gInfo_) + pure $ CPGroupLink (GLPConnectingProhibit gInfo_) | memberActive membership -> pure $ CPGroupLink (GLPKnown gInfo) | otherwise -> pure $ CPGroupLink GLPOk where cReqSchemas :: (ConnReqContact, ConnReqContact) - cReqSchemas = case cReq of - (CRContactUri crData) -> - ( CRContactUri crData {crScheme = CRSSimplex}, - CRContactUri crData {crScheme = simplexChat} - ) - _ -> (cReq, cReq) -- ghc8107 + cReqSchemas = + ( CRContactUri crData {crScheme = CRSSimplex}, + CRContactUri crData {crScheme = simplexChat} + ) cReqHashes :: (ConnReqUriHash, ConnReqUriHash) cReqHashes = bimap hash hash cReqSchemas hash = ConnReqUriHash . C.sha256Hash . strEncode +toggleNtf :: ChatMonad m => User -> GroupMember -> Bool -> m () +toggleNtf user m ntfOn = + when (memberActive m) $ + forM_ (memberConnId m) $ \connId -> + withAgent (\a -> toggleConnectionNtfs a connId ntfOn) `catchChatError` (toView . CRChatError (Just user)) + +data ChangedProfileContact = ChangedProfileContact + { ct :: Contact, + ct' :: Contact, + mergedProfile' :: Profile, + conn :: Connection + } + prepareGroupMsg :: forall m. ChatMonad m => User -> GroupInfo -> MsgContent -> Maybe ChatItemId -> Maybe FileInvitation -> Maybe CITimed -> Bool -> m (MsgContainer, Maybe (CIQuote 'CTGroup)) prepareGroupMsg user GroupInfo {groupId, membership} mc quotedItemId_ fInv_ timed_ live = case quotedItemId_ of Nothing -> pure (MCSimple (ExtMsgContent mc fInv_ (ttl' <$> timed_) (justTrue live)), Nothing) @@ -2511,15 +2635,17 @@ deleteFile user fileInfo = deleteFile' user fileInfo False deleteFile' :: forall m. ChatMonad m => User -> CIFileInfo -> Bool -> m [ConnId] deleteFile' user ciFileInfo@CIFileInfo {filePath} sendCancel = do aConnIds <- cancelFile' user ciFileInfo sendCancel - delete `catchChatError` (toView . CRChatError (Just user)) + forM_ filePath $ \fPath -> + deleteFileLocally fPath `catchChatError` (toView . CRChatError (Just user)) pure aConnIds + +deleteFileLocally :: forall m. ChatMonad m => FilePath -> m () +deleteFileLocally fPath = + withFilesFolder $ \filesFolder -> liftIO $ do + let fsFilePath = filesFolder </> fPath + removeFile fsFilePath `catchAll` \_ -> + removePathForcibly fsFilePath `catchAll_` pure () where - delete :: m () - delete = withFilesFolder $ \filesFolder -> - liftIO . forM_ filePath $ \fPath -> do - let fsFilePath = filesFolder </> fPath - removeFile fsFilePath `catchAll` \_ -> - removePathForcibly fsFilePath `catchAll_` pure () -- perform an action only if filesFolder is set (i.e. on mobile devices) withFilesFolder :: (FilePath -> m ()) -> m () withFilesFolder action = asks filesFolder >>= readTVarIO >>= mapM_ action @@ -2650,14 +2776,14 @@ acceptFileReceive user@User {userId} RcvFileTransfer {fileId, xftpRcvFile, fileI inline <- receiveInline vr <- chatVersionRange if - | inline -> do + | inline -> do -- accepting inline ci <- withStoreCtx (Just "acceptFile, acceptRcvInlineFT") $ \db -> acceptRcvInlineFT db vr user fileId filePath sharedMsgId <- withStore $ \db -> getSharedMsgIdByFileId db userId fileId send $ XFileAcptInv sharedMsgId Nothing fName pure ci - | fileInline == Just IFMSent -> throwChatError $ CEFileAlreadyReceiving fName - | otherwise -> do + | fileInline == Just IFMSent -> throwChatError $ CEFileAlreadyReceiving fName + | otherwise -> do -- accepting via a new connection subMode <- chatReadVar subscriptionMode connIds <- createAgentConnectionAsync user cmdFunction True SCMInvitation subMode @@ -2726,7 +2852,7 @@ getRcvFilePath fileId fPath_ fn keepHandle = case fPath_ of acceptContactRequest :: ChatMonad m => User -> UserContactRequest -> Maybe IncognitoProfile -> Bool -> m Contact acceptContactRequest user UserContactRequest {agentInvitationId = AgentInvId invId, cReqChatVRange, localDisplayName = cName, profileId, profile = cp, userContactLinkId, xContactId} incognitoProfile contactUsed = do subMode <- chatReadVar subscriptionMode - let profileToSend = profileToSendOnAccept user incognitoProfile + let profileToSend = profileToSendOnAccept user incognitoProfile False dm <- directMessage $ XInfo profileToSend acId <- withAgent $ \a -> acceptContact a True invId dm subMode withStore' $ \db -> createAcceptedContact db user acId (fromJVersionRange cReqChatVRange) cName profileId cp userContactLinkId xContactId incognitoProfile subMode contactUsed @@ -2734,7 +2860,7 @@ acceptContactRequest user UserContactRequest {agentInvitationId = AgentInvId inv acceptContactRequestAsync :: ChatMonad m => User -> UserContactRequest -> Maybe IncognitoProfile -> Bool -> m Contact acceptContactRequestAsync user UserContactRequest {agentInvitationId = AgentInvId invId, cReqChatVRange, localDisplayName = cName, profileId, profile = p, userContactLinkId, xContactId} incognitoProfile contactUsed = do subMode <- chatReadVar subscriptionMode - let profileToSend = profileToSendOnAccept user incognitoProfile + let profileToSend = profileToSendOnAccept user incognitoProfile False (cmdId, acId) <- agentAcceptContactAsync user True invId (XInfo profileToSend) subMode withStore' $ \db -> do ct@Contact {activeConn} <- createAcceptedContact db user acId (fromJVersionRange cReqChatVRange) cName profileId p userContactLinkId xContactId incognitoProfile subMode contactUsed @@ -2750,7 +2876,7 @@ acceptGroupJoinRequestAsync incognitoProfile = do gVar <- asks random (groupMemberId, memberId) <- withStore $ \db -> createAcceptedMember db gVar user gInfo ucr gLinkMemRole - let Profile {displayName} = profileToSendOnAccept user incognitoProfile + let Profile {displayName} = profileToSendOnAccept user incognitoProfile True GroupMember {memberRole = userRole, memberId = userMemberId} = membership msg = XGrpLinkInv $ GroupLinkInvitation (MemberIdRole userMemberId userRole) displayName (MemberIdRole memberId gLinkMemRole) groupProfile subMode <- chatReadVar subscriptionMode @@ -2759,7 +2885,7 @@ acceptGroupJoinRequestAsync liftIO $ createAcceptedMemberConnection db user connIds ucr groupMemberId subMode getGroupMemberById db user groupMemberId -profileToSendOnAccept :: User -> Maybe IncognitoProfile -> Profile +profileToSendOnAccept :: User -> Maybe IncognitoProfile -> Bool -> Profile profileToSendOnAccept user ip = userProfileToSend user (getIncognitoProfile <$> ip) Nothing where getIncognitoProfile = \case @@ -2935,9 +3061,9 @@ subscribeUserConnections vr onlyNeeded agentBatchSubscribe user@User {userId} = groupEvent | memberStatus membership == GSMemInvited = CRGroupInvitation user g | all (\GroupMember {activeConn} -> isNothing activeConn) members = - if memberActive membership - then CRGroupEmpty user g - else CRGroupRemoved user g + if memberActive membership + then CRGroupEmpty user g + else CRGroupRemoved user g | otherwise = CRGroupSubscribed user g sndFileSubsToView :: Map ConnId (Either AgentErrorType ()) -> Map ConnId SndFileTransfer -> m () sndFileSubsToView rs sfts = do @@ -3009,11 +3135,11 @@ cleanupManager = do `catchChatError` (toView . CRChatError (Just user)) cleanupMessages = do ts <- liftIO getCurrentTime - let cutoffTs = addUTCTime (- (30 * nominalDay)) ts + let cutoffTs = addUTCTime (-(30 * nominalDay)) ts withStoreCtx' (Just "cleanupManager, deleteOldMessages") (`deleteOldMessages` cutoffTs) cleanupProbes = do ts <- liftIO getCurrentTime - let cutoffTs = addUTCTime (- (14 * nominalDay)) ts + let cutoffTs = addUTCTime (-(14 * nominalDay)) ts withStore' (`deleteOldProbes` cutoffTs) startProximateTimedItemThread :: ChatMonad m => User -> (ChatRef, ChatItemId) -> UTCTime -> m () @@ -3199,7 +3325,7 @@ processAgentMsgSndFile _corrId aFileId msg = _ -> pure () -- TODO error? SFERR e | temporaryAgentError e -> - throwChatError $ CEXFTPSndFile fileId (AgentSndFileId aFileId) e + throwChatError $ CEXFTPSndFile fileId (AgentSndFileId aFileId) e | otherwise -> do ci <- withStore $ \db -> do liftIO $ updateFileCancelled db user fileId CIFSSndError @@ -3273,7 +3399,7 @@ processAgentMsgRcvFile _corrId aFileId msg = toView $ CRRcvFileComplete user ci RFERR e | temporaryAgentError e -> - throwChatError $ CEXFTPRcvFile fileId (AgentRcvFileId aFileId) e + throwChatError $ CEXFTPRcvFile fileId (AgentRcvFileId aFileId) e | otherwise -> do ci <- withStore $ \db -> do liftIO $ updateFileCancelled db user fileId CIFSRcvError @@ -3322,7 +3448,7 @@ processAgentMessageConn vr user@User {userId} corrId agentConnId agentMessage = CONF confId _ connInfo -> do -- [incognito] send saved profile incognitoProfile <- forM customUserProfileId $ \profileId -> withStore (\db -> getProfileById db userId profileId) - let profileToSend = userProfileToSend user (fromLocalProfile <$> incognitoProfile) Nothing + let profileToSend = userProfileToSend user (fromLocalProfile <$> incognitoProfile) Nothing False conn' <- saveConnInfo conn connInfo -- [async agent commands] no continuation needed, but command should be asynchronous for stability allowAgentConnectionAsync user conn' confId $ XInfo profileToSend @@ -3346,6 +3472,9 @@ processAgentMessageConn vr user@User {userId} corrId agentConnId agentMessage = MERR _ err -> do toView $ CRChatError (Just user) (ChatErrorAgent err $ Just connEntity) incAuthErrCounter connEntity conn err + MERRS _ err -> do + -- error cannot be AUTH error here + toView $ CRChatError (Just user) (ChatErrorAgent err $ Just connEntity) ERR err -> do toView $ CRChatError (Just user) (ChatErrorAgent err $ Just connEntity) when (corrId /= "") $ withCompletedCommand conn agentMsg $ \_cmdData -> pure () @@ -3364,6 +3493,7 @@ processAgentMessageConn vr user@User {userId} corrId agentConnId agentMessage = sendXGrpMemInv hostConnId (Just directConnReq) xGrpMemIntroCont CRContactUri _ -> throwChatError $ CECommandError "unexpected ConnectionRequestUri type" MSG msgMeta _msgFlags msgBody -> do + checkIntegrityCreateItem (CDDirectRcv ct) msgMeta cmdId <- createAckCmd conn withAckMessage agentConnId cmdId msgMeta $ do (conn', msg@RcvMessage {chatMsgEvent = ACME _ event}) <- saveDirectRcvMSG conn msgMeta cmdId msgBody @@ -3372,14 +3502,14 @@ processAgentMessageConn vr user@User {userId} corrId agentConnId agentMessage = updateChatLock "directMessage" event case event of XMsgNew mc -> newContentMessage ct' mc msg msgMeta - XMsgFileDescr sharedMsgId fileDescr -> messageFileDescription ct' sharedMsgId fileDescr msgMeta + XMsgFileDescr sharedMsgId fileDescr -> messageFileDescription ct' sharedMsgId fileDescr XMsgUpdate sharedMsgId mContent ttl live -> messageUpdate ct' sharedMsgId mContent msg msgMeta ttl live XMsgDel sharedMsgId _ -> messageDelete ct' sharedMsgId msg msgMeta XMsgReact sharedMsgId _ reaction add -> directMsgReaction ct' sharedMsgId reaction add msg msgMeta -- TODO discontinue XFile XFile fInv -> processFileInvitation' ct' fInv msg msgMeta - XFileCancel sharedMsgId -> xFileCancel ct' sharedMsgId msgMeta - XFileAcptInv sharedMsgId fileConnReq_ fName -> xFileAcptInv ct' sharedMsgId fileConnReq_ fName msgMeta + XFileCancel sharedMsgId -> xFileCancel ct' sharedMsgId + XFileAcptInv sharedMsgId fileConnReq_ fName -> xFileAcptInv ct' sharedMsgId fileConnReq_ fName XInfo p -> xInfo ct' p XDirectDel -> xDirectDel ct' msg msgMeta XGrpInv gInv -> processGroupInvitation ct' gInv msg msgMeta @@ -3387,10 +3517,10 @@ processAgentMessageConn vr user@User {userId} corrId agentConnId agentMessage = XInfoProbeCheck probeHash -> xInfoProbeCheck (COMContact ct') probeHash XInfoProbeOk probe -> xInfoProbeOk (COMContact ct') probe XCallInv callId invitation -> xCallInv ct' callId invitation msg msgMeta - XCallOffer callId offer -> xCallOffer ct' callId offer msg msgMeta - XCallAnswer callId answer -> xCallAnswer ct' callId answer msg msgMeta - XCallExtra callId extraInfo -> xCallExtra ct' callId extraInfo msg msgMeta - XCallEnd callId -> xCallEnd ct' callId msg msgMeta + XCallOffer callId offer -> xCallOffer ct' callId offer msg + XCallAnswer callId answer -> xCallAnswer ct' callId answer msg + XCallExtra callId extraInfo -> xCallExtra ct' callId extraInfo msg + XCallEnd callId -> xCallEnd ct' callId msg BFileChunk sharedMsgId chunk -> bFileChunk ct' sharedMsgId chunk msgMeta _ -> messageError $ "unsupported message: " <> T.pack (show event) let Contact {chatSettings = ChatSettings {sendRcpts}} = ct' @@ -3412,7 +3542,7 @@ processAgentMessageConn vr user@User {userId} corrId agentConnId agentMessage = ct' <- processContactProfileUpdate ct profile False `catchChatError` const (pure ct) -- [incognito] send incognito profile incognitoProfile <- forM customUserProfileId $ \profileId -> withStore $ \db -> getProfileById db userId profileId - let p = userProfileToSend user (fromLocalProfile <$> incognitoProfile) (Just ct') + let p = userProfileToSend user (fromLocalProfile <$> incognitoProfile) (Just ct') False allowAgentConnectionAsync user conn' confId $ XInfo p void $ withStore' $ \db -> resetMemberContactFields db ct' _ -> messageError "CONF for existing contact must have x.grp.mem.info or x.info" @@ -3506,6 +3636,10 @@ processAgentMessageConn vr user@User {userId} corrId agentConnId agentMessage = updateDirectItemStatus ct conn msgId $ agentErrToItemStatus err toView $ CRChatError (Just user) (ChatErrorAgent err $ Just connEntity) incAuthErrCounter connEntity conn err + MERRS msgIds err -> do + -- error cannot be AUTH error here + updateDirectItemsStatus ct conn (L.toList msgIds) $ agentErrToItemStatus err + toView $ CRChatError (Just user) (ChatErrorAgent err $ Just connEntity) ERR err -> do toView $ CRChatError (Just user) (ChatErrorAgent err $ Just connEntity) when (corrId /= "") $ withCompletedCommand conn agentMsg $ \_cmdData -> pure () @@ -3561,18 +3695,20 @@ processAgentMessageConn vr user@User {userId} corrId agentConnId agentMessage = case chatMsgEvent of XGrpAcpt memId | sameMemberId memId m -> do - withStore $ \db -> liftIO $ updateGroupMemberStatus db userId m GSMemAccepted - -- [async agent commands] no continuation needed, but command should be asynchronous for stability - allowAgentConnectionAsync user conn' confId XOk + withStore $ \db -> liftIO $ updateGroupMemberStatus db userId m GSMemAccepted + -- [async agent commands] no continuation needed, but command should be asynchronous for stability + allowAgentConnectionAsync user conn' confId XOk | otherwise -> messageError "x.grp.acpt: memberId is different from expected" _ -> messageError "CONF from invited member must have x.grp.acpt" _ -> case chatMsgEvent of XGrpMemInfo memId _memProfile | sameMemberId memId m -> do - -- TODO update member profile - -- [async agent commands] no continuation needed, but command should be asynchronous for stability - allowAgentConnectionAsync user conn' confId $ XGrpMemInfo (memberId (membership :: GroupMember)) (fromLocalProfile $ memberProfile membership) + let GroupMember {memberId = membershipMemId} = membership + membershipProfile = redactedMemberProfile $ fromLocalProfile $ memberProfile membership + -- TODO update member profile + -- [async agent commands] no continuation needed, but command should be asynchronous for stability + allowAgentConnectionAsync user conn' confId $ XGrpMemInfo membershipMemId membershipProfile | otherwise -> messageError "x.grp.mem.info: memberId is different from expected" _ -> messageError "CONF from member must have x.grp.mem.info" INFO connInfo -> do @@ -3581,8 +3717,8 @@ processAgentMessageConn vr user@User {userId} corrId agentConnId agentMessage = case chatMsgEvent of XGrpMemInfo memId _memProfile | sameMemberId memId m -> do - -- TODO update member profile - pure () + -- TODO update member profile + pure () | otherwise -> messageError "x.grp.mem.info: memberId is different from expected" XInfo _ -> pure () -- sent when connecting via group link XOk -> pure () @@ -3602,7 +3738,11 @@ processAgentMessageConn vr user@User {userId} corrId agentConnId agentMessage = createGroupFeatureItems gInfo m let GroupInfo {groupProfile = GroupProfile {description}} = gInfo memberConnectedChatItem gInfo m - forM_ description $ groupDescriptionChatItem gInfo m + unless expectHistory $ forM_ description $ groupDescriptionChatItem gInfo m + where + expectHistory = + groupFeatureAllowed SGFHistory gInfo + && isCompatibleRange (memberChatVRange' m) groupHistoryIncludeWelcomeVRange GCInviteeMember -> do memberConnectedChatItem gInfo m toView $ CRJoinedGroupMember user gInfo m {memberStatus = GSMemConnected} @@ -3615,18 +3755,23 @@ processAgentMessageConn vr user@User {userId} corrId agentConnId agentMessage = where sendXGrpLinkMem = do let profileMode = ExistingIncognito <$> incognitoMembershipProfile gInfo - profileToSend = profileToSendOnAccept user profileMode + profileToSend = profileToSendOnAccept user profileMode True void $ sendDirectMessage conn (XGrpLinkMem profileToSend) (GroupId groupId) sendIntroductions members = do intros <- withStore' $ \db -> createIntroductions db (maxVersion vr) members m shuffledIntros <- liftIO $ shuffleIntros intros if isCompatibleRange (memberChatVRange' m) batchSendVRange then do - let events = map (XGrpMemIntro . memberInfo . reMember) shuffledIntros + let events = map (memberIntro . reMember) shuffledIntros forM_ (L.nonEmpty events) $ \events' -> sendGroupMemberMessages user conn events' groupId else forM_ shuffledIntros $ \intro -> processIntro intro `catchChatError` (toView . CRChatError (Just user)) + memberIntro :: GroupMember -> ChatMsgEvent 'Json + memberIntro reMember = + let mInfo = memberInfo reMember + mRestrictions = memberRestrictions reMember + in XGrpMemIntro mInfo mRestrictions shuffleIntros :: [GroupMemberIntro] -> IO [GroupMemberIntro] shuffleIntros intros = do let (admins, others) = partition isAdmin intros @@ -3637,7 +3782,7 @@ processAgentMessageConn vr user@User {userId} corrId agentConnId agentMessage = isAdmin GroupMemberIntro {reMember = GroupMember {memberRole}} = memberRole >= GRAdmin hasPicture GroupMemberIntro {reMember = GroupMember {memberProfile = LocalProfile {image}}} = isJust image processIntro intro@GroupMemberIntro {introId} = do - void $ sendDirectMessage conn (XGrpMemIntro $ memberInfo (reMember intro)) (GroupId groupId) + void $ sendDirectMessage conn (memberIntro $ reMember intro) (GroupId groupId) withStore' $ \db -> updateIntroStatus db introId GMIntroSent sendHistory = when (isCompatibleRange (memberChatVRange' m) batchSendVRange) $ do @@ -3645,13 +3790,21 @@ processAgentMessageConn vr user@User {userId} corrId agentConnId agentMessage = (errs', events) <- partitionEithers <$> mapM (tryChatError . itemForwardEvents) items let errors = map ChatErrorStore errs <> errs' unless (null errors) $ toView $ CRChatErrors (Just user) errors - forM_ (L.nonEmpty $ concat events) $ \events' -> - sendGroupMemberMessages user conn events' groupId + let events' = maybe (concat events) (\x -> concat events <> [x]) descrEvent_ + forM_ (L.nonEmpty events') $ \events'' -> + sendGroupMemberMessages user conn events'' groupId + descrEvent_ :: Maybe (ChatMsgEvent 'Json) + descrEvent_ + | isCompatibleRange (memberChatVRange' m) groupHistoryIncludeWelcomeVRange = do + let GroupInfo {groupProfile = GroupProfile {description}} = gInfo + fmap (\descr -> XMsgNew $ MCSimple $ extMsgContent (MCText descr) Nothing) description + | otherwise = Nothing itemForwardEvents :: CChatItem 'CTGroup -> m [ChatMsgEvent 'Json] itemForwardEvents cci = case cci of - (CChatItem SMDRcv ci@ChatItem {chatDir = CIGroupRcv sender, content = CIRcvMsgContent mc, file}) -> do - fInvDescr_ <- join <$> forM file getRcvFileInvDescr - processContentItem sender ci mc fInvDescr_ + (CChatItem SMDRcv ci@ChatItem {chatDir = CIGroupRcv sender, content = CIRcvMsgContent mc, file}) + | not (blockedByAdmin sender) -> do + fInvDescr_ <- join <$> forM file getRcvFileInvDescr + processContentItem sender ci mc fInvDescr_ (CChatItem SMDSnd ci@ChatItem {content = CISndMsgContent mc, file}) -> do fInvDescr_ <- join <$> forM file getSndFileInvDescr processContentItem membership ci mc fInvDescr_ @@ -3687,7 +3840,7 @@ processAgentMessageConn vr user@User {userId} corrId agentConnId agentMessage = fInv = xftpFileInvitation fileName fileSize fInvDescr in Just (fInv, fileDescrText) | otherwise = Nothing - processContentItem :: GroupMember -> ChatItem 'CTGroup d -> MsgContent -> Maybe (FileInvitation, RcvFileDescrText) -> m [ChatMsgEvent Json] + processContentItem :: GroupMember -> ChatItem 'CTGroup d -> MsgContent -> Maybe (FileInvitation, RcvFileDescrText) -> m [ChatMsgEvent 'Json] processContentItem sender ChatItem {meta, quotedItem} mc fInvDescr_ = if isNothing fInvDescr_ && not (msgContentHasText mc) then pure [] @@ -3722,20 +3875,21 @@ processAgentMessageConn vr user@User {userId} corrId agentConnId agentMessage = when (memCategory == GCPreMember) $ probeMatchingContactsAndMembers ct connectedIncognito True sendXGrpMemCon memCategory where + GroupMember {memberId} = m sendXGrpMemCon = \case GCPreMember -> forM_ (invitedByGroupMemberId membership) $ \hostId -> do host <- withStore $ \db -> getGroupMember db user groupId hostId forM_ (memberConn host) $ \hostConn -> - void $ sendDirectMessage hostConn (XGrpMemCon $ memberId (m :: GroupMember)) (GroupId groupId) + void $ sendDirectMessage hostConn (XGrpMemCon memberId) (GroupId groupId) GCPostMember -> forM_ (invitedByGroupMemberId m) $ \invitingMemberId -> do im <- withStore $ \db -> getGroupMember db user groupId invitingMemberId forM_ (memberConn im) $ \imConn -> - void $ sendDirectMessage imConn (XGrpMemCon $ memberId (m :: GroupMember)) (GroupId groupId) + void $ sendDirectMessage imConn (XGrpMemCon memberId) (GroupId groupId) _ -> messageWarning "sendXGrpMemCon: member category GCPreMember or GCPostMember is expected" MSG msgMeta _msgFlags msgBody -> do - checkIntegrityCreateItem (CDGroupRcv gInfo m) msgMeta `catchChatError` \_ -> pure () + checkIntegrityCreateItem (CDGroupRcv gInfo m) msgMeta cmdId <- createAckCmd conn let aChatMsgs = parseChatMessages msgBody withAckMessage agentConnId cmdId msgMeta $ do @@ -3745,7 +3899,8 @@ processAgentMessageConn vr user@User {userId} corrId agentConnId agentMessage = Left e -> toView $ CRChatError (Just user) (ChatError . CEException $ "error parsing chat message: " <> e) checkSendRcpt $ rights aChatMsgs -- currently only a single message is forwarded - when (memberRole (membership :: GroupMember) >= GRAdmin) $ case aChatMsgs of + let GroupMember {memberRole = membershipMemRole} = membership + when (membershipMemRole >= GRAdmin && not (blockedByAdmin m)) $ case aChatMsgs of [Right (ACMsg _ chatMsg)] -> forwardMsg_ chatMsg _ -> pure () where @@ -3767,10 +3922,11 @@ processAgentMessageConn vr user@User {userId} corrId agentConnId agentMessage = XInfo p -> xInfoMember gInfo m' p XGrpLinkMem p -> xGrpLinkMem gInfo m' conn' p XGrpMemNew memInfo -> xGrpMemNew gInfo m' memInfo msg brokerTs - XGrpMemIntro memInfo -> xGrpMemIntro gInfo m' memInfo + XGrpMemIntro memInfo memRestrictions_ -> xGrpMemIntro gInfo m' memInfo memRestrictions_ XGrpMemInv memId introInv -> xGrpMemInv gInfo m' memId introInv XGrpMemFwd memInfo introInv -> xGrpMemFwd gInfo m' memInfo introInv XGrpMemRole memId memRole -> xGrpMemRole gInfo m' memId memRole msg brokerTs + XGrpMemRestrict memId memRestrictions -> xGrpMemRestrict gInfo m' memId memRestrictions msg brokerTs XGrpMemCon memId -> xGrpMemCon gInfo m' memId XGrpMemDel memId -> xGrpMemDel gInfo m' memId msg brokerTs XGrpLeave -> xGrpLeave gInfo m' msg brokerTs @@ -3805,10 +3961,11 @@ processAgentMessageConn vr user@User {userId} corrId agentConnId agentMessage = else pure [] -- invited members to which this member was introduced invitedMembers <- withStore' $ \db -> getForwardInvitedMembers db user m highlyAvailable - let ms = introducedMembers <> invitedMembers - msg = XGrpMsgForward (memberId (m :: GroupMember)) chatMsg' brokerTs + let GroupMember {memberId} = m + ms = forwardedToGroupMembers (introducedMembers <> invitedMembers) chatMsg' + msg = XGrpMsgForward memberId chatMsg' brokerTs unless (null ms) . void $ - sendGroupMessage user gInfo ms msg + sendGroupMessage' user gInfo ms msg RCVD msgMeta msgRcpt -> withAckMessage' agentConnId conn msgMeta $ groupMsgReceived gInfo m conn msgMeta msgRcpt @@ -3853,18 +4010,26 @@ processAgentMessageConn vr user@User {userId} corrId agentConnId agentMessage = withCompletedCommand conn agentMsg $ \CommandData {cmdFunction, cmdId} -> when (cmdFunction == CFAckMessage) $ ackMsgDeliveryEvent conn cmdId MERR msgId err -> do - chatItemId_ <- withStore' $ \db -> getChatItemIdByAgentMsgId db connId msgId - forM_ chatItemId_ $ \itemId -> do - let GroupMember {groupMemberId} = m - updateGroupMemSndStatus itemId groupMemberId $ agentErrToItemStatus err + withStore' $ \db -> updateGroupItemErrorStatus db msgId (groupMemberId' m) $ agentErrToItemStatus err -- group errors are silenced to reduce load on UI event log -- toView $ CRChatError (Just user) (ChatErrorAgent err $ Just connEntity) incAuthErrCounter connEntity conn err + MERRS msgIds err -> do + let newStatus = agentErrToItemStatus err + -- error cannot be AUTH error here + withStore' $ \db -> forM_ msgIds $ \msgId -> + updateGroupItemErrorStatus db msgId (groupMemberId' m) newStatus `catchAll_` pure () + toView $ CRChatError (Just user) (ChatErrorAgent err $ Just connEntity) ERR err -> do toView $ CRChatError (Just user) (ChatErrorAgent err $ Just connEntity) when (corrId /= "") $ withCompletedCommand conn agentMsg $ \_cmdData -> pure () -- TODO add debugging output _ -> pure () + where + updateGroupItemErrorStatus :: DB.Connection -> AgentMsgId -> GroupMemberId -> CIStatus 'MDSnd -> IO () + updateGroupItemErrorStatus db msgId groupMemberId newStatus = do + chatItemId_ <- getChatItemIdByAgentMsgId db connId msgId + forM_ chatItemId_ $ \itemId -> updateGroupMemSndStatus' db itemId groupMemberId newStatus agentMsgDecryptError :: AgentCryptoError -> (MsgDecryptError, Word32) agentMsgDecryptError = \case @@ -3878,11 +4043,11 @@ processAgentMessageConn vr user@User {userId} corrId agentConnId agentMessage = mdeUpdatedCI :: (MsgDecryptError, Word32) -> CChatItem c -> Maybe (ChatItem c 'MDRcv, CIContent 'MDRcv) mdeUpdatedCI (mde', n') (CChatItem _ ci@ChatItem {content = CIRcvDecryptionError mde n}) | mde == mde' = case mde of - MDERatchetHeader -> r (n + n') - MDETooManySkipped -> r n' -- the numbers are not added as sequential MDETooManySkipped will have it incremented by 1 - MDERatchetEarlier -> r (n + n') - MDEOther -> r (n + n') - MDERatchetSync -> r 0 + MDERatchetHeader -> r (n + n') + MDETooManySkipped -> r n' -- the numbers are not added as sequential MDETooManySkipped will have it incremented by 1 + MDERatchetEarlier -> r (n + n') + MDEOther -> r (n + n') + MDERatchetSync -> r 0 | otherwise = Nothing where r n'' = Just (ci, CIRcvDecryptionError mde n'') @@ -3900,9 +4065,9 @@ processAgentMessageConn vr user@User {userId} corrId agentConnId agentMessage = -- TODO save XFileAcpt message XFileAcpt name | name == fileName -> do - withStore' $ \db -> updateSndFileStatus db ft FSAccepted - -- [async agent commands] no continuation needed, but command should be asynchronous for stability - allowAgentConnectionAsync user conn' confId XOk + withStore' $ \db -> updateSndFileStatus db ft FSAccepted + -- [async agent commands] no continuation needed, but command should be asynchronous for stability + allowAgentConnectionAsync user conn' confId XOk | otherwise -> messageError "x.file.acpt: fileName is different from expected" _ -> messageError "CONF from file connection must have x.file.acpt" CON -> do @@ -4094,8 +4259,8 @@ processAgentMessageConn vr user@User {userId} corrId agentConnId agentMessage = case cmdData_ of Just cmdData@CommandData {cmdId, cmdConnId = Just cmdConnId', cmdFunction} | connId == cmdConnId' && (agentMsgTag == commandExpectedResponse cmdFunction || agentMsgTag == APCT SAEConn ERR_) -> do - withStore' $ \db -> deleteCommand db user cmdId - action cmdData + withStore' $ \db -> deleteCommand db user cmdId + action cmdData | otherwise -> err cmdId $ "not matching connection id or unexpected response, corrId = " <> show corrId Just CommandData {cmdId, cmdConnId = Nothing} -> err cmdId $ "no command connection id, corrId = " <> show corrId Nothing -> throwChatError . CEAgentCommandError $ "command not found, corrId = " <> show corrId @@ -4224,7 +4389,6 @@ processAgentMessageConn vr user@User {userId} corrId agentConnId agentMessage = newContentMessage :: Contact -> MsgContainer -> RcvMessage -> MsgMeta -> m () newContentMessage ct@Contact {contactUsed} mc msg@RcvMessage {sharedMsgId_} msgMeta = do unless contactUsed $ withStore' $ \db -> updateContactUsed db user ct - checkIntegrityCreateItem (CDDirectRcv ct) msgMeta let ExtMsgContent content fInv_ _ _ = mcExtMsgContent mc -- Uncomment to test stuck delivery on errors - see test testDirectMessageDelete -- case content of @@ -4254,9 +4418,8 @@ processAgentMessageConn vr user@User {userId} corrId agentConnId agentMessage = ChatConfig {autoAcceptFileSize = sz} <- asks config when (sz > fileSize) $ receiveFile' user ft Nothing Nothing >>= toView - messageFileDescription :: Contact -> SharedMsgId -> FileDescr -> MsgMeta -> m () - messageFileDescription ct@Contact {contactId} sharedMsgId fileDescr msgMeta = do - checkIntegrityCreateItem (CDDirectRcv ct) msgMeta + messageFileDescription :: Contact -> SharedMsgId -> FileDescr -> m () + messageFileDescription Contact {contactId} sharedMsgId fileDescr = do fileId <- withStore $ \db -> getFileIdBySharedMsgId db userId contactId sharedMsgId processFDMessage fileId fileDescr @@ -4299,7 +4462,6 @@ processAgentMessageConn vr user@User {userId} corrId agentConnId agentMessage = messageUpdate :: Contact -> SharedMsgId -> MsgContent -> RcvMessage -> MsgMeta -> Maybe Int -> Maybe Bool -> m () messageUpdate ct@Contact {contactId} sharedMsgId mc msg@RcvMessage {msgId} msgMeta ttl live_ = do - checkIntegrityCreateItem (CDDirectRcv ct) msgMeta updateRcvChatItem `catchCINotFound` \_ -> do -- This patches initial sharedMsgId into chat item when locally deleted chat item -- received an update from the sender, so that it can be referenced later (e.g. by broadcast delete). @@ -4332,10 +4494,10 @@ processAgentMessageConn vr user@User {userId} corrId agentConnId agentMessage = _ -> messageError "x.msg.update: contact attempted invalid message update" messageDelete :: Contact -> SharedMsgId -> RcvMessage -> MsgMeta -> m () - messageDelete ct@Contact {contactId} sharedMsgId RcvMessage {msgId} msgMeta@MsgMeta {broker = (_, brokerTs)} = do - checkIntegrityCreateItem (CDDirectRcv ct) msgMeta + messageDelete ct@Contact {contactId} sharedMsgId RcvMessage {msgId} msgMeta = do deleteRcvChatItem `catchCINotFound` (toView . CRChatItemDeletedNotFound user ct) where + brokerTs = metaBrokerTs msgMeta deleteRcvChatItem = do CChatItem msgDir ci <- withStore $ \db -> getDirectChatItemBySharedMsgId db user contactId sharedMsgId case msgDir of @@ -4398,37 +4560,49 @@ processAgentMessageConn vr user@User {userId} corrId agentConnId agentMessage = newGroupContentMessage :: GroupInfo -> GroupMember -> MsgContainer -> RcvMessage -> UTCTime -> Bool -> m () newGroupContentMessage gInfo m@GroupMember {memberId, memberRole} mc msg@RcvMessage {sharedMsgId_} brokerTs forwarded + | blockedByAdmin m = createBlockedByAdmin | isVoice content && not (groupFeatureAllowed SGFVoice gInfo) = rejected GFVoice | not (isVoice content) && isJust fInv_ && not (groupFeatureAllowed SGFFiles gInfo) = rejected GFFiles - | otherwise = do - let timed_ = - if forwarded - then rcvCITimed_ (Just Nothing) itemTTL - else rcvGroupCITimed gInfo itemTTL - live = fromMaybe False live_ + | otherwise = withStore' (\db -> getCIModeration db user gInfo memberId sharedMsgId_) >>= \case Just ciModeration -> do - applyModeration timed_ live ciModeration + applyModeration ciModeration withStore' $ \db -> deleteCIModeration db gInfo memberId sharedMsgId_ - Nothing -> createItem timed_ live + Nothing -> createContentItem where rejected f = void $ newChatItem (CIRcvGroupFeatureRejected f) Nothing Nothing False + timed' = if forwarded then rcvCITimed_ (Just Nothing) itemTTL else rcvGroupCITimed gInfo itemTTL + live' = fromMaybe False live_ ExtMsgContent content fInv_ itemTTL live_ = mcExtMsgContent mc - applyModeration timed_ live CIModeration {moderatorMember = moderator@GroupMember {memberRole = moderatorRole}, createdByMsgId, moderatedAt} - | moderatorRole < GRAdmin || moderatorRole < memberRole = - createItem timed_ live + createBlockedByAdmin | groupFeatureAllowed SGFFullDelete gInfo = do - ci <- saveRcvChatItem' user (CDGroupRcv gInfo m) msg sharedMsgId_ brokerTs CIRcvModerated Nothing timed_ False - ci' <- withStore' $ \db -> updateGroupChatItemModerated db user gInfo ci moderator moderatedAt - toView $ CRNewChatItem user $ AChatItem SCTGroup SMDRcv (GroupChat gInfo) ci' + ci <- saveRcvChatItem' user (CDGroupRcv gInfo m) msg sharedMsgId_ brokerTs CIRcvBlocked Nothing timed' False + ci' <- withStore' $ \db -> updateGroupCIBlockedByAdmin db user gInfo ci brokerTs + groupMsgToView gInfo ci' | otherwise = do - file_ <- processFileInvitation fInv_ content $ \db -> createRcvGroupFileTransfer db userId m - ci <- saveRcvChatItem' user (CDGroupRcv gInfo m) msg sharedMsgId_ brokerTs (CIRcvMsgContent content) (snd <$> file_) timed_ False - toView =<< markGroupCIDeleted user gInfo ci createdByMsgId False (Just moderator) moderatedAt - createItem timed_ live = do - file_ <- processFileInvitation fInv_ content $ \db -> createRcvGroupFileTransfer db userId m - newChatItem (CIRcvMsgContent content) (snd <$> file_) timed_ live + file_ <- processFileInv + ci <- createNonLive file_ + ci' <- withStore' $ \db -> markGroupCIBlockedByAdmin db user gInfo ci + groupMsgToView gInfo ci' + applyModeration CIModeration {moderatorMember = moderator@GroupMember {memberRole = moderatorRole}, createdByMsgId, moderatedAt} + | moderatorRole < GRAdmin || moderatorRole < memberRole = + createContentItem + | groupFeatureAllowed SGFFullDelete gInfo = do + ci <- saveRcvChatItem' user (CDGroupRcv gInfo m) msg sharedMsgId_ brokerTs CIRcvModerated Nothing timed' False + ci' <- withStore' $ \db -> updateGroupChatItemModerated db user gInfo ci moderator moderatedAt + groupMsgToView gInfo ci' + | otherwise = do + file_ <- processFileInv + ci <- createNonLive file_ + toView =<< markGroupCIDeleted user gInfo ci createdByMsgId False (Just moderator) moderatedAt + createNonLive file_ = + saveRcvChatItem' user (CDGroupRcv gInfo m) msg sharedMsgId_ brokerTs (CIRcvMsgContent content) (snd <$> file_) timed' False + createContentItem = do + file_ <- processFileInv + newChatItem (CIRcvMsgContent content) (snd <$> file_) timed' live' when (showMessages $ memberSettings m) $ autoAcceptFile file_ + processFileInv = + processFileInvitation fInv_ content $ \db -> createRcvGroupFileTransfer db userId m newChatItem ciContent ciFile_ timed_ live = do ci <- saveRcvChatItem' user (CDGroupRcv gInfo m) msg sharedMsgId_ brokerTs ciContent ciFile_ timed_ live ci' <- blockedMember m ci $ withStore' $ \db -> markGroupChatItemBlocked db user gInfo ci @@ -4493,7 +4667,7 @@ processAgentMessageConn vr user@User {userId} corrId agentConnId agentMessage = _ -> messageError "x.msg.del: message of another member without memberId" checkRole GroupMember {memberRole} a | senderRole < GRAdmin || senderRole < memberRole = - messageError "x.msg.del: message of another member with insufficient member permissions" + messageError "x.msg.del: message of another member with insufficient member permissions" | otherwise = a delete :: MsgDirectionI d => ChatItem 'CTGroup d -> Maybe GroupMember -> m ChatResponse delete ci byGroupMember @@ -4503,7 +4677,6 @@ processAgentMessageConn vr user@User {userId} corrId agentConnId agentMessage = -- TODO remove once XFile is discontinued processFileInvitation' :: Contact -> FileInvitation -> RcvMessage -> MsgMeta -> m () processFileInvitation' ct fInv@FileInvitation {fileName, fileSize} msg@RcvMessage {sharedMsgId_} msgMeta = do - checkIntegrityCreateItem (CDDirectRcv ct) msgMeta ChatConfig {fileChunkSize} <- asks config inline <- receiveInlineMode fInv Nothing fileChunkSize RcvFileTransfer {fileId, xftpRcvFile} <- withStore $ \db -> createRcvFileTransfer db userId ct fInv inline fileChunkSize @@ -4540,9 +4713,8 @@ processAgentMessageConn vr user@User {userId} corrId agentConnId agentMessage = inline' receiveInstant = if mode == IFMOffer || (receiveInstant && maybe False isVoice mc_) then fileInline else Nothing _ -> pure Nothing - xFileCancel :: Contact -> SharedMsgId -> MsgMeta -> m () - xFileCancel ct@Contact {contactId} sharedMsgId msgMeta = do - checkIntegrityCreateItem (CDDirectRcv ct) msgMeta + xFileCancel :: Contact -> SharedMsgId -> m () + xFileCancel Contact {contactId} sharedMsgId = do fileId <- withStore $ \db -> getFileIdBySharedMsgId db userId contactId sharedMsgId ft <- withStore (\db -> getRcvFileTransfer db user fileId) unless (rcvFileCompleteOrCancelled ft) $ do @@ -4550,9 +4722,8 @@ processAgentMessageConn vr user@User {userId} corrId agentConnId agentMessage = ci <- withStore $ \db -> getChatItemByFileId db vr user fileId toView $ CRRcvFileSndCancelled user ci ft - xFileAcptInv :: Contact -> SharedMsgId -> Maybe ConnReqInvitation -> String -> MsgMeta -> m () - xFileAcptInv ct sharedMsgId fileConnReq_ fName msgMeta = do - checkIntegrityCreateItem (CDDirectRcv ct) msgMeta + xFileAcptInv :: Contact -> SharedMsgId -> Maybe ConnReqInvitation -> String -> m () + xFileAcptInv ct sharedMsgId fileConnReq_ fName = do fileId <- withStore $ \db -> getDirectFileIdBySharedMsgId db user ct sharedMsgId (AChatItem _ _ _ ci) <- withStore $ \db -> getChatItemByFileId db vr user fileId assertSMPAcceptNotProhibited ci @@ -4686,16 +4857,15 @@ processAgentMessageConn vr user@User {userId} corrId agentConnId agentMessage = let Contact {localDisplayName = c, activeConn} = ct GroupInvitation {fromMember = (MemberIdRole fromMemId fromRole), invitedMember = (MemberIdRole memId memRole), connRequest, groupLinkId} = inv forM_ activeConn $ \Connection {connId, peerChatVRange, customUserProfileId, groupLinkId = groupLinkId'} -> do - checkIntegrityCreateItem (CDDirectRcv ct) msgMeta when (fromRole < GRAdmin || fromRole < memRole) $ throwChatError (CEGroupContactRole c) when (fromMemId == memId) $ throwChatError CEGroupDuplicateMemberId -- [incognito] if direct connection with host is incognito, create membership using the same incognito profile - (gInfo@GroupInfo {groupId, localDisplayName, groupProfile, membership = membership@GroupMember {groupMemberId, memberId}}, hostId) <- - withStore $ \db -> createGroupInvitation db vr user ct inv customUserProfileId + (gInfo@GroupInfo {groupId, localDisplayName, groupProfile, membership}, hostId) <- withStore $ \db -> createGroupInvitation db vr user ct inv customUserProfileId + let GroupMember {groupMemberId, memberId = membershipMemId} = membership if sameGroupLinkId groupLinkId groupLinkId' then do subMode <- chatReadVar subscriptionMode - dm <- directMessage $ XGrpAcpt memberId + dm <- directMessage $ XGrpAcpt membershipMemId connIds <- joinAgentConnectionAsync user True connRequest dm subMode withStore' $ \db -> do setViaGroupLinkHash db groupId connId @@ -4718,7 +4888,9 @@ processAgentMessageConn vr user@User {userId} corrId agentConnId agentMessage = checkIntegrityCreateItem :: forall c. ChatTypeI c => ChatDirection c 'MDRcv -> MsgMeta -> m () checkIntegrityCreateItem cd MsgMeta {integrity, broker = (_, brokerTs)} = case integrity of MsgOk -> pure () - MsgError e -> createInternalChatItem user cd (CIRcvIntegrityError e) (Just brokerTs) + MsgError e -> + createInternalChatItem user cd (CIRcvIntegrityError e) (Just brokerTs) + `catchChatError` \_ -> pure () xInfo :: Contact -> Profile -> m () xInfo c p' = void $ processContactProfileUpdate c p' True @@ -4727,7 +4899,6 @@ processAgentMessageConn vr user@User {userId} corrId agentConnId agentMessage = xDirectDel c msg msgMeta = if directOrUsed c then do - checkIntegrityCreateItem (CDDirectRcv c) msgMeta ct' <- withStore' $ \db -> updateContactStatus db user c CSDeleted contactConns <- withStore' $ \db -> getContactConnections db userId ct' deleteAgentConnectionsAsync user $ map aConnId contactConns @@ -4745,20 +4916,23 @@ processAgentMessageConn vr user@User {userId} corrId agentConnId agentMessage = brokerTs = metaBrokerTs msgMeta processContactProfileUpdate :: Contact -> Profile -> Bool -> m Contact - processContactProfileUpdate c@Contact {profile = p} p' createItems - | fromLocalProfile p /= p' = do - c' <- withStore $ \db -> - if userTTL == rcvTTL - then updateContactProfile db user c p' - else do - c' <- liftIO $ updateContactUserPreferences db user c ctUserPrefs' - updateContactProfile db user c' p' - when (directOrUsed c' && createItems) $ createRcvFeatureItems user c c' - toView $ CRContactUpdated user c c' - pure c' + processContactProfileUpdate c@Contact {profile = lp} p' createItems + | p /= p' = do + c' <- withStore $ \db -> + if userTTL == rcvTTL + then updateContactProfile db user c p' + else do + c' <- liftIO $ updateContactUserPreferences db user c ctUserPrefs' + updateContactProfile db user c' p' + when (directOrUsed c' && createItems) $ do + createProfileUpdatedItem c' + createRcvFeatureItems user c c' + toView $ CRContactUpdated user c c' + pure c' | otherwise = - pure c + pure c where + p = fromLocalProfile lp Contact {userPreferences = ctUserPrefs@Preferences {timedMessages = ctUserTMPref}} = c userTTL = prefParam $ getPreference SCFTimedMessages ctUserPrefs Profile {preferences = rcvPrefs_} = p' @@ -4772,32 +4946,62 @@ processAgentMessageConn vr user@User {userId} corrId agentConnId agentMessage = | rcvTTL /= userDefaultTTL -> Just (userDefault :: TimedMessagesPreference) {ttl = rcvTTL} | otherwise -> Nothing in setPreference_ SCFTimedMessages ctUserTMPref' ctUserPrefs + createProfileUpdatedItem c' = + when visibleProfileUpdated $ do + let ciContent = CIRcvDirectEvent $ RDEProfileUpdated p p' + createInternalChatItem user (CDDirectRcv c') ciContent Nothing + where + visibleProfileUpdated = + n' /= n || fn' /= fn || i' /= i || cl' /= cl + Profile {displayName = n, fullName = fn, image = i, contactLink = cl} = p + Profile {displayName = n', fullName = fn', image = i', contactLink = cl'} = p' xInfoMember :: GroupInfo -> GroupMember -> Profile -> m () - xInfoMember gInfo m p' = void $ processMemberProfileUpdate gInfo m p' + xInfoMember gInfo m p' = void $ processMemberProfileUpdate gInfo m p' True xGrpLinkMem :: GroupInfo -> GroupMember -> Connection -> Profile -> m () xGrpLinkMem gInfo@GroupInfo {membership} m@GroupMember {groupMemberId, memberCategory} Connection {viaGroupLink} p' = do xGrpLinkMemReceived <- withStore $ \db -> getXGrpLinkMemReceived db groupMemberId if viaGroupLink && isNothing (memberContactId m) && memberCategory == GCHostMember && not xGrpLinkMemReceived then do - m' <- processMemberProfileUpdate gInfo m p' + m' <- processMemberProfileUpdate gInfo m p' False withStore' $ \db -> setXGrpLinkMemReceived db groupMemberId True let connectedIncognito = memberIncognito membership probeMatchingMemberContact m' connectedIncognito else messageError "x.grp.link.mem error: invalid group link host profile update" - processMemberProfileUpdate :: GroupInfo -> GroupMember -> Profile -> m GroupMember - processMemberProfileUpdate gInfo m@GroupMember {memberContactId} p' = - case memberContactId of - Nothing -> do - m' <- withStore $ \db -> updateMemberProfile db user m p' - toView $ CRGroupMemberUpdated user gInfo m m' - pure m' - Just mContactId -> do - mCt <- withStore $ \db -> getContact db user mContactId - Contact {profile} <- processContactProfileUpdate mCt p' True - pure m {memberProfile = profile} + processMemberProfileUpdate :: GroupInfo -> GroupMember -> Profile -> Bool -> m GroupMember + processMemberProfileUpdate gInfo m@GroupMember {memberProfile = p, memberContactId} p' createItems + | redactedMemberProfile (fromLocalProfile p) /= redactedMemberProfile p' = + case memberContactId of + Nothing -> do + m' <- withStore $ \db -> updateMemberProfile db user m p' + createProfileUpdatedItem m' + toView $ CRGroupMemberUpdated user gInfo m m' + pure m' + Just mContactId -> do + mCt <- withStore $ \db -> getContact db user mContactId + if canUpdateProfile mCt + then do + (m', ct') <- withStore $ \db -> updateContactMemberProfile db user m mCt p' + createProfileUpdatedItem m' + toView $ CRGroupMemberUpdated user gInfo m m' + toView $ CRContactUpdated user mCt ct' + pure m' + else pure m + where + canUpdateProfile ct + | not (contactActive ct) = True + | otherwise = case contactConn ct of + Nothing -> True + Just conn -> not (connReady conn) || (authErrCounter conn >= 1) + | otherwise = + pure m + where + createProfileUpdatedItem m' = + when createItems $ do + let ciContent = CIRcvGroupEvent $ RGEMemberProfileUpdated (fromLocalProfile p) p' + createInternalChatItem user (CDGroupRcv gInfo m') ciContent Nothing createFeatureEnabledItems :: Contact -> m () createFeatureEnabledItems ct@Contact {mergedPreferences} = @@ -4807,7 +5011,7 @@ processAgentMessageConn vr user@User {userId} corrId agentConnId agentMessage = createGroupFeatureItems :: GroupInfo -> GroupMember -> m () createGroupFeatureItems g@GroupInfo {fullGroupPreferences} m = - forM_ allGroupFeatureItems $ \(AGF f) -> do + forM_ allGroupFeatures $ \(AGF f) -> do let p = getGroupPreference f fullGroupPreferences (_, param) = groupFeatureState p createInternalChatItem user (CDGroupRcv g m) (CIRcvGroupFeature (toGroupFeature f) (toGroupPreference p) param) Nothing @@ -4845,21 +5049,21 @@ processAgentMessageConn vr user@User {userId} corrId agentConnId agentMessage = case cgm2 of COMContact c2@Contact {contactId = cId2, profile = p2} | cId1 /= cId2 && profilesMatch p1 p2 -> do - void . sendDirectContactMessage c1 $ XInfoProbeOk probe - COMContact <$$> mergeContacts c1 c2 + void . sendDirectContactMessage c1 $ XInfoProbeOk probe + COMContact <$$> mergeContacts c1 c2 | otherwise -> messageWarning "probeMatch ignored: profiles don't match or same contact id" >> pure Nothing COMGroupMember m2@GroupMember {memberProfile = p2, memberContactId} | isNothing memberContactId && profilesMatch p1 p2 -> do - void . sendDirectContactMessage c1 $ XInfoProbeOk probe - COMContact <$$> associateMemberAndContact c1 m2 + void . sendDirectContactMessage c1 $ XInfoProbeOk probe + COMContact <$$> associateMemberAndContact c1 m2 | otherwise -> messageWarning "probeMatch ignored: profiles don't match or member already has contact" >> pure Nothing COMGroupMember GroupMember {activeConn = Nothing} -> pure Nothing COMGroupMember m1@GroupMember {groupId, memberProfile = p1, memberContactId, activeConn = Just conn} -> case cgm2 of COMContact c2@Contact {profile = p2} | memberCurrent m1 && isNothing memberContactId && profilesMatch p1 p2 -> do - void $ sendDirectMessage conn (XInfoProbeOk probe) (GroupId groupId) - COMContact <$$> associateMemberAndContact c2 m1 + void $ sendDirectMessage conn (XInfoProbeOk probe) (GroupId groupId) + COMContact <$$> associateMemberAndContact c2 m1 | otherwise -> messageWarning "probeMatch ignored: profiles don't match or member already has contact or member not current" >> pure Nothing COMGroupMember _ -> messageWarning "probeMatch ignored: members are not matched with members" >> pure Nothing @@ -4887,7 +5091,6 @@ processAgentMessageConn vr user@User {userId} corrId agentConnId agentMessage = -- to party accepting call xCallInv :: Contact -> CallId -> CallInvitation -> RcvMessage -> MsgMeta -> m () xCallInv ct@Contact {contactId} callId CallInvitation {callType, callDhPubKey} msg@RcvMessage {sharedMsgId_} msgMeta = do - checkIntegrityCreateItem (CDDirectRcv ct) msgMeta if featureAllowed SCFCalls forContact ct then do g <- asks random @@ -4914,9 +5117,9 @@ processAgentMessageConn vr user@User {userId} corrId agentConnId agentMessage = toView $ CRNewChatItem user (AChatItem SCTDirect SMDRcv (DirectChat ct) ci) -- to party initiating call - xCallOffer :: Contact -> CallId -> CallOffer -> RcvMessage -> MsgMeta -> m () - xCallOffer ct callId CallOffer {callType, rtcSession, callDhPubKey} msg msgMeta = do - msgCurrentCall ct callId "x.call.offer" msg msgMeta $ + xCallOffer :: Contact -> CallId -> CallOffer -> RcvMessage -> m () + xCallOffer ct callId CallOffer {callType, rtcSession, callDhPubKey} msg = do + msgCurrentCall ct callId "x.call.offer" msg $ \call -> case callState call of CallInvitationSent {localCallType, localDhPrivKey} -> do let sharedKey = C.Key . C.dhBytes' <$> (C.dh' <$> callDhPubKey <*> localDhPrivKey) @@ -4929,9 +5132,9 @@ processAgentMessageConn vr user@User {userId} corrId agentConnId agentMessage = pure (Just call, Nothing) -- to party accepting call - xCallAnswer :: Contact -> CallId -> CallAnswer -> RcvMessage -> MsgMeta -> m () - xCallAnswer ct callId CallAnswer {rtcSession} msg msgMeta = do - msgCurrentCall ct callId "x.call.answer" msg msgMeta $ + xCallAnswer :: Contact -> CallId -> CallAnswer -> RcvMessage -> m () + xCallAnswer ct callId CallAnswer {rtcSession} msg = do + msgCurrentCall ct callId "x.call.answer" msg $ \call -> case callState call of CallOfferSent {localCallType, peerCallType, localCallSession, sharedKey} -> do let callState' = CallNegotiated {localCallType, peerCallType, localCallSession, peerCallSession = rtcSession, sharedKey} @@ -4942,9 +5145,9 @@ processAgentMessageConn vr user@User {userId} corrId agentConnId agentMessage = pure (Just call, Nothing) -- to any call party - xCallExtra :: Contact -> CallId -> CallExtraInfo -> RcvMessage -> MsgMeta -> m () - xCallExtra ct callId CallExtraInfo {rtcExtraInfo} msg msgMeta = do - msgCurrentCall ct callId "x.call.extra" msg msgMeta $ + xCallExtra :: Contact -> CallId -> CallExtraInfo -> RcvMessage -> m () + xCallExtra ct callId CallExtraInfo {rtcExtraInfo} msg = do + msgCurrentCall ct callId "x.call.extra" msg $ \call -> case callState call of CallOfferReceived {localCallType, peerCallType, peerCallSession, sharedKey} -> do -- TODO update the list of ice servers in peerCallSession @@ -4961,31 +5164,30 @@ processAgentMessageConn vr user@User {userId} corrId agentConnId agentMessage = pure (Just call, Nothing) -- to any call party - xCallEnd :: Contact -> CallId -> RcvMessage -> MsgMeta -> m () - xCallEnd ct callId msg msgMeta = - msgCurrentCall ct callId "x.call.end" msg msgMeta $ \Call {chatItemId} -> do + xCallEnd :: Contact -> CallId -> RcvMessage -> m () + xCallEnd ct callId msg = + msgCurrentCall ct callId "x.call.end" msg $ \Call {chatItemId} -> do toView $ CRCallEnded user ct (Nothing,) <$> callStatusItemContent user ct chatItemId WCSDisconnected - msgCurrentCall :: Contact -> CallId -> Text -> RcvMessage -> MsgMeta -> (Call -> m (Maybe Call, Maybe ACIContent)) -> m () - msgCurrentCall ct@Contact {contactId = ctId'} callId' eventName RcvMessage {msgId} msgMeta action = do - checkIntegrityCreateItem (CDDirectRcv ct) msgMeta + msgCurrentCall :: Contact -> CallId -> Text -> RcvMessage -> (Call -> m (Maybe Call, Maybe ACIContent)) -> m () + msgCurrentCall ct@Contact {contactId = ctId'} callId' eventName RcvMessage {msgId} action = do calls <- asks currentCalls atomically (TM.lookup ctId' calls) >>= \case Nothing -> messageError $ eventName <> ": no current call" Just call@Call {contactId, callId, chatItemId} | contactId /= ctId' || callId /= callId' -> messageError $ eventName <> ": wrong contact or callId" | otherwise -> do - (call_, aciContent_) <- action call - case call_ of - Just call' -> do - unless (isRcvInvitation call') $ withStore' $ \db -> deleteCalls db user ctId' - atomically $ TM.insert ctId' call' calls - _ -> do - withStore' $ \db -> deleteCalls db user ctId' - atomically $ TM.delete ctId' calls - forM_ aciContent_ $ \aciContent -> - updateDirectChatItemView user ct chatItemId aciContent False $ Just msgId + (call_, aciContent_) <- action call + case call_ of + Just call' -> do + unless (isRcvInvitation call') $ withStore' $ \db -> deleteCalls db user ctId' + atomically $ TM.insert ctId' call' calls + _ -> do + withStore' $ \db -> deleteCalls db user ctId' + atomically $ TM.delete ctId' calls + forM_ aciContent_ $ \aciContent -> + updateDirectChatItemView user ct chatItemId aciContent False $ Just msgId msgCallStateError :: Text -> Call -> m () msgCallStateError eventName Call {callState} = @@ -5036,8 +5238,8 @@ processAgentMessageConn vr user@User {userId} corrId agentConnId agentMessage = suffixOrd displayName localDisplayName | localDisplayName == displayName = Just 0 | otherwise = case T.stripPrefix (displayName <> "_") localDisplayName of - Just suffix -> readMaybe $ T.unpack suffix - Nothing -> Nothing + Just suffix -> readMaybe $ T.unpack suffix + Nothing -> Nothing associateMemberWithContact :: Contact -> GroupMember -> m Contact associateMemberWithContact c1 m2@GroupMember {groupId} = do @@ -5071,19 +5273,27 @@ processAgentMessageConn vr user@User {userId} corrId agentConnId agentMessage = _ -> pure conn' xGrpMemNew :: GroupInfo -> GroupMember -> MemberInfo -> RcvMessage -> UTCTime -> m () - xGrpMemNew gInfo m memInfo@(MemberInfo memId memRole _ memberProfile) msg brokerTs = do + xGrpMemNew gInfo m memInfo@(MemberInfo memId memRole _ _) msg brokerTs = do checkHostRole m memRole unless (sameMemberId memId $ membership gInfo) $ withStore' (\db -> runExceptT $ getGroupMemberByMemberId db user gInfo memId) >>= \case + Right unknownMember@GroupMember {memberStatus = GSMemUnknown} -> do + updatedMember <- withStore $ \db -> updateUnknownMemberAnnounced db user m unknownMember memInfo + toView $ CRUnknownMemberAnnounced user gInfo m unknownMember updatedMember + memberAnnouncedToView updatedMember Right _ -> messageError "x.grp.mem.new error: member already exists" Left _ -> do - newMember@GroupMember {groupMemberId} <- withStore $ \db -> createNewGroupMember db user gInfo m memInfo GCPostMember GSMemAnnounced - ci <- saveRcvChatItem user (CDGroupRcv gInfo m) msg brokerTs (CIRcvGroupEvent $ RGEMemberAdded groupMemberId memberProfile) - groupMsgToView gInfo ci - toView $ CRJoinedGroupMemberConnecting user gInfo m newMember + newMember <- withStore $ \db -> createNewGroupMember db user gInfo m memInfo GCPostMember GSMemAnnounced + memberAnnouncedToView newMember + where + memberAnnouncedToView announcedMember@GroupMember {groupMemberId, memberProfile} = do + let event = RGEMemberAdded groupMemberId (fromLocalProfile memberProfile) + ci <- saveRcvChatItem user (CDGroupRcv gInfo m) msg brokerTs (CIRcvGroupEvent event) + groupMsgToView gInfo ci + toView $ CRJoinedGroupMemberConnecting user gInfo m announcedMember - xGrpMemIntro :: GroupInfo -> GroupMember -> MemberInfo -> m () - xGrpMemIntro gInfo@GroupInfo {chatSettings} m@GroupMember {memberRole, localDisplayName = c} memInfo@(MemberInfo memId _ memChatVRange _) = do + xGrpMemIntro :: GroupInfo -> GroupMember -> MemberInfo -> Maybe MemberRestrictions -> m () + xGrpMemIntro gInfo@GroupInfo {chatSettings} m@GroupMember {memberRole, localDisplayName = c} memInfo@(MemberInfo memId _ memChatVRange _) memRestrictions = do case memberCategory m of GCHostMember -> withStore' (\db -> runExceptT $ getGroupMemberByMemberId db user gInfo memId) >>= \case @@ -5099,7 +5309,7 @@ processAgentMessageConn vr user@User {userId} corrId agentConnId agentMessage = | isCompatibleRange (fromChatVRange mcvr) groupNoDirectVRange -> pure Nothing | otherwise -> Just <$> createConn subMode let customUserProfileId = localProfileId <$> incognitoMembershipProfile gInfo - void $ withStore $ \db -> createIntroReMember db user gInfo m memInfo groupConnIds directConnIds customUserProfileId subMode + void $ withStore $ \db -> createIntroReMember db user gInfo m memInfo memRestrictions groupConnIds directConnIds customUserProfileId subMode _ -> messageError "x.grp.mem.intro can be only sent by host member" where createConn subMode = createAgentConnectionAsync user CFCreateConnGrpMemInv (chatHasNtfs chatSettings) SCMInvitation subMode @@ -5126,6 +5336,7 @@ processAgentMessageConn vr user@User {userId} corrId agentConnId agentMessage = xGrpMemFwd :: GroupInfo -> GroupMember -> MemberInfo -> IntroInvitation -> m () xGrpMemFwd gInfo@GroupInfo {membership, chatSettings} m memInfo@(MemberInfo memId memRole memChatVRange _) introInv@IntroInvitation {groupConnReq, directConnReq} = do + let GroupMember {memberId = membershipMemId} = membership checkHostRole m memRole toMember <- withStore' (\db -> runExceptT $ getGroupMemberByMemberId db user gInfo memId) >>= \case @@ -5138,7 +5349,8 @@ processAgentMessageConn vr user@User {userId} corrId agentConnId agentMessage = withStore' $ \db -> saveMemberInvitation db toMember introInv subMode <- chatReadVar subscriptionMode -- [incognito] send membership incognito profile, create direct connection as incognito - dm <- directMessage $ XGrpMemInfo (memberId (membership :: GroupMember)) (fromLocalProfile $ memberProfile membership) + let membershipProfile = redactedMemberProfile $ fromLocalProfile $ memberProfile membership + dm <- directMessage $ XGrpMemInfo membershipMemId membershipProfile -- [async agent commands] no continuation needed, but commands should be asynchronous for stability groupConnIds <- joinAgentConnectionAsync user (chatHasNtfs chatSettings) groupConnReq dm subMode directConnIds <- forM directConnReq $ \dcr -> joinAgentConnectionAsync user True dcr dm subMode @@ -5148,26 +5360,61 @@ processAgentMessageConn vr user@User {userId} corrId agentConnId agentMessage = xGrpMemRole :: GroupInfo -> GroupMember -> MemberId -> GroupMemberRole -> RcvMessage -> UTCTime -> m () xGrpMemRole gInfo@GroupInfo {membership} m@GroupMember {memberRole = senderRole} memId memRole msg brokerTs - | memberId (membership :: GroupMember) == memId = - let gInfo' = gInfo {membership = membership {memberRole = memRole}} - in changeMemberRole gInfo' membership $ RGEUserRole memRole + | membershipMemId == memId = + let gInfo' = gInfo {membership = membership {memberRole = memRole}} + in changeMemberRole gInfo' membership $ RGEUserRole memRole | otherwise = - withStore' (\db -> runExceptT $ getGroupMemberByMemberId db user gInfo memId) >>= \case - Right member -> changeMemberRole gInfo member $ RGEMemberRole (groupMemberId' member) (fromLocalProfile $ memberProfile member) memRole - Left _ -> messageError "x.grp.mem.role with unknown member ID" + withStore' (\db -> runExceptT $ getGroupMemberByMemberId db user gInfo memId) >>= \case + Right member -> changeMemberRole gInfo member $ RGEMemberRole (groupMemberId' member) (fromLocalProfile $ memberProfile member) memRole + Left _ -> messageError "x.grp.mem.role with unknown member ID" where + GroupMember {memberId = membershipMemId} = membership changeMemberRole gInfo' member@GroupMember {memberRole = fromRole} gEvent | senderRole < GRAdmin || senderRole < fromRole = messageError "x.grp.mem.role with insufficient member permissions" | otherwise = do - withStore' $ \db -> updateGroupMemberRole db user member memRole - ci <- saveRcvChatItem user (CDGroupRcv gInfo m) msg brokerTs (CIRcvGroupEvent gEvent) - groupMsgToView gInfo ci - toView CRMemberRole {user, groupInfo = gInfo', byMember = m, member = member {memberRole = memRole}, fromRole, toRole = memRole} + withStore' $ \db -> updateGroupMemberRole db user member memRole + ci <- saveRcvChatItem user (CDGroupRcv gInfo m) msg brokerTs (CIRcvGroupEvent gEvent) + groupMsgToView gInfo ci + toView CRMemberRole {user, groupInfo = gInfo', byMember = m, member = member {memberRole = memRole}, fromRole, toRole = memRole} checkHostRole :: GroupMember -> GroupMemberRole -> m () checkHostRole GroupMember {memberRole, localDisplayName} memRole = when (memberRole < GRAdmin || memberRole < memRole) $ throwChatError (CEGroupContactRole localDisplayName) + xGrpMemRestrict :: GroupInfo -> GroupMember -> MemberId -> MemberRestrictions -> RcvMessage -> UTCTime -> m () + xGrpMemRestrict + gInfo@GroupInfo {groupId, membership = GroupMember {memberId = membershipMemId}} + m@GroupMember {memberRole = senderRole} + memId + MemberRestrictions {restriction} + msg + brokerTs + | membershipMemId == memId = + -- member shouldn't receive this message about themselves + messageError "x.grp.mem.restrict: admin blocks you" + | otherwise = + withStore' (\db -> runExceptT $ getGroupMemberByMemberId db user gInfo memId) >>= \case + Right bm@GroupMember {groupMemberId = bmId, memberRole, memberProfile = bmp} + | senderRole < GRAdmin || senderRole < memberRole -> messageError "x.grp.mem.restrict with insufficient member permissions" + | otherwise -> do + bm' <- setMemberBlocked bmId + toggleNtf user bm' (not blocked) + let ciContent = CIRcvGroupEvent $ RGEMemberBlocked bmId (fromLocalProfile bmp) blocked + ci <- saveRcvChatItem user (CDGroupRcv gInfo m) msg brokerTs ciContent + groupMsgToView gInfo ci + toView CRMemberBlockedForAll {user, groupInfo = gInfo, byMember = m, member = bm, blocked} + Left (SEGroupMemberNotFoundByMemberId _) -> do + bm <- createUnknownMember gInfo memId + bm' <- setMemberBlocked $ groupMemberId' bm + toView $ CRUnknownMemberBlocked user gInfo m bm' + Left e -> throwError $ ChatErrorStore e + where + setMemberBlocked bmId = + withStore $ \db -> do + liftIO $ updateGroupMemberBlocked db user groupId bmId restriction + getGroupMember db user groupId bmId + blocked = mrsBlocked restriction + xGrpMemCon :: GroupInfo -> GroupMember -> MemberId -> m () xGrpMemCon gInfo sendingMember memId = do refMember <- withStore $ \db -> getGroupMemberByMemberId db user gInfo memId @@ -5209,7 +5456,8 @@ processAgentMessageConn vr user@User {userId} corrId agentConnId agentMessage = xGrpMemDel :: GroupInfo -> GroupMember -> MemberId -> RcvMessage -> UTCTime -> m () xGrpMemDel gInfo@GroupInfo {membership} m@GroupMember {memberRole = senderRole} memId msg brokerTs = do - if memberId (membership :: GroupMember) == memId + let GroupMember {memberId = membershipMemId} = membership + if membershipMemId == memId then checkRole membership $ do deleteGroupLinkIfExists user gInfo -- member records are not deleted to keep history @@ -5232,7 +5480,7 @@ processAgentMessageConn vr user@User {userId} corrId agentConnId agentMessage = where checkRole GroupMember {memberRole} a | senderRole < GRAdmin || senderRole < memberRole = - messageError "x.grp.mem.del with insufficient member permissions" + messageError "x.grp.mem.del with insufficient member permissions" | otherwise = a deleteMemberItem gEvent = do ci <- saveRcvChatItem user (CDGroupRcv gInfo m) msg brokerTs (CIRcvGroupEvent gEvent) @@ -5264,13 +5512,13 @@ processAgentMessageConn vr user@User {userId} corrId agentConnId agentMessage = xGrpInfo g@GroupInfo {groupProfile = p} m@GroupMember {memberRole} p' msg brokerTs | memberRole < GROwner = messageError "x.grp.info with insufficient member permissions" | otherwise = unless (p == p') $ do - g' <- withStore $ \db -> updateGroupProfile db user g p' - toView $ CRGroupUpdated user g g' (Just m) - let cd = CDGroupRcv g' m - unless (sameGroupProfileInfo p p') $ do - ci <- saveRcvChatItem user cd msg brokerTs (CIRcvGroupEvent $ RGEGroupUpdated p') - groupMsgToView g' ci - createGroupFeatureChangedItems user cd CIRcvGroupFeature g g' + g' <- withStore $ \db -> updateGroupProfile db user g p' + toView $ CRGroupUpdated user g g' (Just m) + let cd = CDGroupRcv g' m + unless (sameGroupProfileInfo p p') $ do + ci <- saveRcvChatItem user cd msg brokerTs (CIRcvGroupEvent $ RGEGroupUpdated p') + groupMsgToView g' ci + createGroupFeatureChangedItems user cd CIRcvGroupFeature g g' xGrpDirectInv :: GroupInfo -> GroupMember -> Connection -> ConnReqInvitation -> Maybe MsgContent -> RcvMessage -> UTCTime -> m () xGrpDirectInv g m mConn connReq mContent_ msg brokerTs = do @@ -5305,7 +5553,7 @@ processAgentMessageConn vr user@User {userId} corrId agentConnId agentMessage = createItems mCt' m' joinConn subMode = do -- [incognito] send membership incognito profile - let p = userProfileToSend user (fromLocalProfile <$> incognitoMembershipProfile g) Nothing + let p = userProfileToSend user (fromLocalProfile <$> incognitoMembershipProfile g) Nothing False dm <- directMessage $ XInfo p joinAgentConnectionAsync user True connReq dm subMode createItems mCt' m' = do @@ -5323,8 +5571,13 @@ processAgentMessageConn vr user@User {userId} corrId agentConnId agentMessage = xGrpMsgForward :: GroupInfo -> GroupMember -> MemberId -> ChatMessage 'Json -> UTCTime -> m () xGrpMsgForward gInfo@GroupInfo {groupId} m@GroupMember {memberRole, localDisplayName} memberId msg msgTs = do when (memberRole < GRAdmin) $ throwChatError (CEGroupContactRole localDisplayName) - author <- withStore $ \db -> getGroupMemberByMemberId db user gInfo memberId - processForwardedMsg author msg + withStore' (\db -> runExceptT $ getGroupMemberByMemberId db user gInfo memberId) >>= \case + Right author -> processForwardedMsg author msg + Left (SEGroupMemberNotFoundByMemberId _) -> do + unknownAuthor <- createUnknownMember gInfo memberId + toView $ CRUnknownMemberCreated user gInfo m unknownAuthor + processForwardedMsg unknownAuthor msg + Left e -> throwError $ ChatErrorStore e where -- Note: forwarded group events (see forwardedGroupMsg) should include msgId to be deduplicated processForwardedMsg :: GroupMember -> ChatMessage 'Json -> m () @@ -5347,6 +5600,11 @@ processAgentMessageConn vr user@User {userId} corrId agentConnId agentMessage = XGrpInfo p' -> xGrpInfo gInfo author p' rcvMsg msgTs _ -> messageError $ "x.grp.msg.forward: unsupported forwarded event " <> T.pack (show $ toCMEventTag event) + createUnknownMember :: GroupInfo -> MemberId -> m GroupMember + createUnknownMember gInfo memberId = do + let name = T.take 7 . safeDecodeUtf8 . B64.encode . unMemberId $ memberId + withStore $ \db -> createNewUnknownGroupMember db vr user gInfo memberId name + directMsgReceived :: Contact -> Connection -> MsgMeta -> NonEmpty MsgReceipt -> m () directMsgReceived ct conn@Connection {connId} msgMeta msgRcpts = do checkIntegrityCreateItem (CDDirectRcv ct) msgMeta @@ -5366,24 +5624,39 @@ processAgentMessageConn vr user@User {userId} corrId agentConnId agentMessage = withStore' $ \db -> updateSndMsgDeliveryStatus db connId agentMsgId $ MDSSndRcvd msgRcptStatus updateGroupItemStatus gInfo m conn agentMsgId $ CISSndRcvd msgRcptStatus SSPComplete - updateDirectItemStatus :: Contact -> Connection -> AgentMsgId -> CIStatus 'MDSnd -> m () - updateDirectItemStatus ct@Contact {contactId} Connection {connId} msgId newStatus = - withStore' (\db -> getDirectChatItemByAgentMsgId db user contactId connId msgId) >>= \case - Just (CChatItem SMDSnd ChatItem {meta = CIMeta {itemStatus = CISSndRcvd _ _}}) -> pure () - Just (CChatItem SMDSnd ChatItem {meta = CIMeta {itemId, itemStatus}}) - | itemStatus == newStatus -> pure () - | otherwise -> do - chatItem <- withStore $ \db -> updateDirectChatItemStatus db user ct itemId newStatus - toView $ CRChatItemStatusUpdated user (AChatItem SCTDirect SMDSnd (DirectChat ct) chatItem) + updateDirectItemsStatus :: Contact -> Connection -> [AgentMsgId] -> CIStatus 'MDSnd -> m () + updateDirectItemsStatus ct conn msgIds newStatus = do + cis_ <- withStore' $ \db -> forM msgIds $ \msgId -> runExceptT $ updateDirectItemStatus' db ct conn msgId newStatus + -- only send the last expired item event to view + case catMaybes $ rights $ reverse cis_ of + ci : _ -> toView $ CRChatItemStatusUpdated user (AChatItem SCTDirect SMDSnd (DirectChat ct) ci) _ -> pure () + updateDirectItemStatus :: Contact -> Connection -> AgentMsgId -> CIStatus 'MDSnd -> m () + updateDirectItemStatus ct conn msgId newStatus = do + ci_ <- withStore $ \db -> updateDirectItemStatus' db ct conn msgId newStatus + forM_ ci_ $ \ci -> toView $ CRChatItemStatusUpdated user (AChatItem SCTDirect SMDSnd (DirectChat ct) ci) + + updateDirectItemStatus' :: DB.Connection -> Contact -> Connection -> AgentMsgId -> CIStatus 'MDSnd -> ExceptT StoreError IO (Maybe (ChatItem 'CTDirect 'MDSnd)) + updateDirectItemStatus' db ct@Contact {contactId} Connection {connId} msgId newStatus = + liftIO (getDirectChatItemByAgentMsgId db user contactId connId msgId) >>= \case + Just (CChatItem SMDSnd ChatItem {meta = CIMeta {itemStatus = CISSndRcvd _ _}}) -> pure Nothing + Just (CChatItem SMDSnd ChatItem {meta = CIMeta {itemId, itemStatus}}) + | itemStatus == newStatus -> pure Nothing + | otherwise -> Just <$> updateDirectChatItemStatus db user ct itemId newStatus + _ -> pure Nothing + updateGroupMemSndStatus :: ChatItemId -> GroupMemberId -> CIStatus 'MDSnd -> m Bool updateGroupMemSndStatus itemId groupMemberId newStatus = - runExceptT (withStore $ \db -> getGroupSndStatus db itemId groupMemberId) >>= \case + withStore' $ \db -> updateGroupMemSndStatus' db itemId groupMemberId newStatus + + updateGroupMemSndStatus' :: DB.Connection -> ChatItemId -> GroupMemberId -> CIStatus 'MDSnd -> IO Bool + updateGroupMemSndStatus' db itemId groupMemberId newStatus = + runExceptT (getGroupSndStatus db itemId groupMemberId) >>= \case Right (CISSndRcvd _ _) -> pure False Right memStatus | memStatus == newStatus -> pure False - | otherwise -> withStore' (\db -> updateGroupSndStatus db itemId groupMemberId newStatus) $> True + | otherwise -> updateGroupSndStatus db itemId groupMemberId newStatus $> True _ -> pure False updateGroupItemStatus :: GroupInfo -> GroupMember -> Connection -> AgentMsgId -> CIStatus 'MDSnd -> m () @@ -5499,7 +5772,7 @@ parseFileChunk :: ChatMonad m => ByteString -> m FileChunk parseFileChunk = liftEither . first (ChatError . CEFileRcvChunk) . smpDecode appendFileChunk :: forall m. ChatMonad m => RcvFileTransfer -> Integer -> ByteString -> Bool -> m () -appendFileChunk ft@RcvFileTransfer {fileId, fileInvitation, fileStatus, cryptoArgs} chunkNo chunk final = +appendFileChunk ft@RcvFileTransfer {fileId, fileStatus, cryptoArgs, fileInvitation = FileInvitation {fileName}} chunkNo chunk final = case fileStatus of RFSConnected RcvFileInfo {filePath} -> append_ filePath -- sometimes update of file transfer status to FSConnected @@ -5517,7 +5790,7 @@ appendFileChunk ft@RcvFileTransfer {fileId, fileInvitation, fileStatus, cryptoAr when final $ do closeFileHandle fileId rcvFiles forM_ cryptoArgs $ \cfArgs -> do - tmpFile <- getChatTempDirectory >>= (`uniqueCombine` fileName (fileInvitation :: FileInvitation)) + tmpFile <- getChatTempDirectory >>= (`uniqueCombine` fileName) tryChatError (liftError encryptErr $ encryptFile fsFilePath tmpFile cfArgs) >>= \case Right () -> do removeFile fsFilePath `catchChatError` \_ -> pure () @@ -5621,12 +5894,20 @@ deleteOrUpdateMemberRecord user@User {userId} member = Nothing -> deleteGroupMember db user member sendDirectContactMessage :: (MsgEncodingI e, ChatMonad m) => Contact -> ChatMsgEvent e -> m (SndMessage, Int64) -sendDirectContactMessage ct@Contact {activeConn = Nothing} _ = throwChatError $ CEContactNotReady ct -sendDirectContactMessage ct@Contact {activeConn = Just conn@Connection {connId, connStatus}, contactStatus} chatMsgEvent - | connStatus /= ConnReady && connStatus /= ConnSndReady = throwChatError $ CEContactNotReady ct - | contactStatus /= CSActive = throwChatError $ CEContactNotActive ct - | connDisabled conn = throwChatError $ CEContactDisabled ct - | otherwise = sendDirectMessage conn chatMsgEvent (ConnectionId connId) +sendDirectContactMessage ct chatMsgEvent = do + conn@Connection {connId} <- liftEither $ contactSendConn_ ct + sendDirectMessage conn chatMsgEvent (ConnectionId connId) + +contactSendConn_ :: Contact -> Either ChatError Connection +contactSendConn_ ct@Contact {activeConn} = case activeConn of + Nothing -> err $ CEContactNotReady ct + Just conn + | not (connReady conn) -> err $ CEContactNotReady ct + | not (contactActive ct) -> err $ CEContactNotActive ct + | connDisabled conn -> err $ CEContactDisabled ct + | otherwise -> Right conn + where + err = Left . ChatError sendDirectMessage :: (MsgEncodingI e, ChatMonad m) => Connection -> ChatMsgEvent e -> ConnOrGroupId -> m (SndMessage, Int64) sendDirectMessage conn chatMsgEvent connOrGroupId = do @@ -5635,18 +5916,25 @@ sendDirectMessage conn chatMsgEvent connOrGroupId = do (msg,) <$> deliverMessage conn (toCMEventTag chatMsgEvent) msgBody msgId createSndMessage :: (MsgEncodingI e, ChatMonad m) => ChatMsgEvent e -> ConnOrGroupId -> m SndMessage -createSndMessage chatMsgEvent connOrGroupId = do +createSndMessage chatMsgEvent connOrGroupId = + liftEither . runIdentity =<< createSndMessages (Identity (connOrGroupId, chatMsgEvent)) + +createSndMessages :: forall e m t. (MsgEncodingI e, ChatMonad' m, Traversable t) => t (ConnOrGroupId, ChatMsgEvent e) -> m (t (Either ChatError SndMessage)) +createSndMessages idsEvents = do gVar <- asks random vr <- chatVersionRange - withStore $ \db -> createNewSndMessage db gVar connOrGroupId chatMsgEvent (encodeMessage vr) + withStoreBatch $ \db -> fmap (uncurry (createMsg db gVar vr)) idsEvents where - encodeMessage chatVRange sharedMsgId = - encodeChatMessage ChatMessage {chatVRange, msgId = Just sharedMsgId, chatMsgEvent} + createMsg db gVar chatVRange connOrGroupId evnt = runExceptT $ do + withExceptT ChatErrorStore $ createNewSndMessage db gVar connOrGroupId evnt (encodeMessage chatVRange evnt) + encodeMessage chatVRange evnt sharedMsgId = + encodeChatMessage ChatMessage {chatVRange, msgId = Just sharedMsgId, chatMsgEvent = evnt} sendGroupMemberMessages :: forall e m. (MsgEncodingI e, ChatMonad m) => User -> Connection -> NonEmpty (ChatMsgEvent e) -> GroupId -> m () sendGroupMemberMessages user conn@Connection {connId} events groupId = do when (connDisabled conn) $ throwChatError (CEConnectionDisabled conn) - (errs, msgs) <- partitionEithers <$> createSndMessages + let idsEvts = L.map (GroupId groupId,) events + (errs, msgs) <- partitionEithers . L.toList <$> createSndMessages idsEvts unless (null errs) $ toView $ CRChatErrors (Just user) errs unless (null msgs) $ do let (errs', msgBatches) = partitionEithers $ batchMessages maxChatMsgSize msgs @@ -5660,16 +5948,6 @@ sendGroupMemberMessages user conn@Connection {connId} events groupId = do agentMsgId <- withAgent $ \a -> sendMessage a (aConnId conn) MsgFlags {notification = True} batchBody let sndMsgDelivery = SndMsgDelivery {connId, agentMsgId} void . withStoreBatch' $ \db -> map (\SndMessage {msgId} -> createSndMsgDelivery db sndMsgDelivery msgId) sndMsgs - createSndMessages :: m [Either ChatError SndMessage] - createSndMessages = do - gVar <- asks random - vr <- chatVersionRange - withStoreBatch $ \db -> map (createMsg db gVar vr) (toList events) - createMsg db gVar chatVRange evnt = do - r <- runExceptT $ createNewSndMessage db gVar (GroupId groupId) evnt (encodeMessage chatVRange evnt) - pure $ first ChatErrorStore r - encodeMessage chatVRange evnt sharedMsgId = - encodeChatMessage ChatMessage {chatVRange, msgId = Just sharedMsgId, chatMsgEvent = evnt} directMessage :: (MsgEncodingI e, ChatMonad m) => ChatMsgEvent e -> m ByteString directMessage chatMsgEvent = do @@ -5690,19 +5968,50 @@ deliverMessage' conn msgFlags msgBody msgId = [r] -> liftEither r rs -> throwChatError $ CEInternalError $ "deliverMessage: expected 1 result, got " <> show (length rs) -deliverMessages :: ChatMonad' m => [(Connection, MsgFlags, MsgBody, MessageId)] -> m [Either ChatError Int64] -deliverMessages msgReqs = do - sent <- zipWith prepareBatch msgReqs <$> withAgent' (`sendMessages` aReqs) +type MsgReq = (Connection, MsgFlags, MsgBody, MessageId) + +deliverMessages :: ChatMonad' m => [MsgReq] -> m [Either ChatError Int64] +deliverMessages = deliverMessagesB . map Right + +deliverMessagesB :: ChatMonad' m => [Either ChatError MsgReq] -> m [Either ChatError Int64] +deliverMessagesB msgReqs = do + sent <- zipWith prepareBatch msgReqs <$> withAgent' (`sendMessagesB` map toAgent msgReqs) withStoreBatch $ \db -> map (bindRight $ createDelivery db) sent where - aReqs = map (\(conn, msgFlags, msgBody, _msgId) -> (aConnId conn, msgFlags, msgBody)) msgReqs - prepareBatch req = bimap (`ChatErrorAgent` Nothing) (req,) - createDelivery :: DB.Connection -> ((Connection, MsgFlags, MsgBody, MessageId), AgentMsgId) -> IO (Either ChatError Int64) + toAgent = \case + Right (conn, msgFlags, msgBody, _msgId) -> Right (aConnId conn, msgFlags, msgBody) + Left _ce -> Left (AP.INTERNAL "ChatError, skip") -- as long as it is Left, the agent batchers should just step over it + prepareBatch (Right req) (Right ar) = Right (req, ar) + prepareBatch (Left ce) _ = Left ce -- restore original ChatError + prepareBatch _ (Left ae) = Left $ ChatErrorAgent ae Nothing + createDelivery :: DB.Connection -> (MsgReq, AgentMsgId) -> IO (Either ChatError Int64) createDelivery db ((Connection {connId}, _, _, msgId), agentMsgId) = Right <$> createSndMsgDelivery db (SndMsgDelivery {connId, agentMsgId}) msgId sendGroupMessage :: (MsgEncodingI e, ChatMonad m) => User -> GroupInfo -> [GroupMember] -> ChatMsgEvent e -> m (SndMessage, [GroupMember]) -sendGroupMessage user GroupInfo {groupId} members chatMsgEvent = do +sendGroupMessage user gInfo members chatMsgEvent = do + when shouldSendProfileUpdate $ + sendProfileUpdate `catchChatError` (\e -> toView (CRChatError (Just user) e)) + sendGroupMessage' user gInfo members chatMsgEvent + where + User {profile = p, userMemberProfileUpdatedAt} = user + GroupInfo {userMemberProfileSentAt} = gInfo + shouldSendProfileUpdate + | incognitoMembership gInfo = False + | otherwise = + case (userMemberProfileSentAt, userMemberProfileUpdatedAt) of + (Just lastSentTs, Just lastUpdateTs) -> lastSentTs < lastUpdateTs + (Nothing, Just _) -> True + _ -> False + sendProfileUpdate = do + let members' = filter (\m -> isCompatibleRange (memberChatVRange' m) memberProfileUpdateVRange) members + profileUpdateEvent = XInfo $ redactedMemberProfile $ fromLocalProfile p + void $ sendGroupMessage' user gInfo members' profileUpdateEvent + currentTs <- liftIO getCurrentTime + withStore' $ \db -> updateUserMemberProfileSentAt db user gInfo currentTs + +sendGroupMessage' :: (MsgEncodingI e, ChatMonad m) => User -> GroupInfo -> [GroupMember] -> ChatMsgEvent e -> m (SndMessage, [GroupMember]) +sendGroupMessage' user GroupInfo {groupId} members chatMsgEvent = do msg@SndMessage {msgId, msgBody} <- createSndMessage chatMsgEvent (GroupId groupId) recipientMembers <- liftIO $ shuffleMembers (filter memberCurrent members) let msgFlags = MsgFlags {notification = hasNotification $ toCMEventTag chatMsgEvent} @@ -5731,7 +6040,7 @@ sendGroupMessage user GroupInfo {groupId} members chatMsgEvent = do data MemberSendAction = MSASend Connection | MSAPending memberSendAction :: ChatMsgEvent e -> [GroupMember] -> GroupMember -> Maybe MemberSendAction -memberSendAction chatMsgEvent members m = case memberConn m of +memberSendAction chatMsgEvent members m@GroupMember {invitedByGroupMemberId} = case memberConn m of Nothing -> pendingOrForwarded Just conn@Connection {connStatus} | connDisabled conn || connStatus == ConnDeleted -> Nothing @@ -5746,7 +6055,7 @@ memberSendAction chatMsgEvent members m = case memberConn m of forwardSupported = let mcvr = memberChatVRange' m in isCompatibleRange mcvr groupForwardVRange && invitingMemberSupportsForward - invitingMemberSupportsForward = case invitedByGroupMemberId m of + invitingMemberSupportsForward = case invitedByGroupMemberId of Just invMemberId -> -- can be optimized for large groups by replacing [GroupMember] with Map GroupMemberId GroupMember case find (\m' -> groupMemberId' m' == invMemberId) members of @@ -5801,42 +6110,41 @@ saveDirectRcvMSG conn@Connection {connId} agentMsgMeta agentAckCmdId msgBody = saveGroupRcvMsg :: (MsgEncodingI e, ChatMonad m) => User -> GroupId -> GroupMember -> Connection -> MsgMeta -> CommandId -> MsgBody -> ChatMessage e -> m (GroupMember, Connection, RcvMessage) saveGroupRcvMsg user groupId authorMember conn@Connection {connId} agentMsgMeta agentAckCmdId msgBody ChatMessage {chatVRange, msgId = sharedMsgId_, chatMsgEvent} = do - (am', conn') <- updateMemberChatVRange authorMember conn chatVRange + (am'@GroupMember {memberId = amMemId, groupMemberId = amGroupMemId}, conn') <- updateMemberChatVRange authorMember conn chatVRange let agentMsgId = fst $ recipient agentMsgMeta newMsg = NewRcvMessage {chatMsgEvent, msgBody} rcvMsgDelivery = RcvMsgDelivery {connId, agentMsgId, agentMsgMeta, agentAckCmdId} - amId = Just $ groupMemberId' am' msg <- - withStore (\db -> createNewMessageAndRcvMsgDelivery db (GroupId groupId) newMsg sharedMsgId_ rcvMsgDelivery amId) + withStore (\db -> createNewMessageAndRcvMsgDelivery db (GroupId groupId) newMsg sharedMsgId_ rcvMsgDelivery $ Just amGroupMemId) `catchChatError` \e -> case e of ChatErrorStore (SEDuplicateGroupMessage _ _ _ (Just forwardedByGroupMemberId)) -> do fm <- withStore $ \db -> getGroupMember db user groupId forwardedByGroupMemberId forM_ (memberConn fm) $ \fmConn -> - void $ sendDirectMessage fmConn (XGrpMemCon $ memberId (am' :: GroupMember)) (GroupId groupId) + void $ sendDirectMessage fmConn (XGrpMemCon amMemId) (GroupId groupId) throwError e _ -> throwError e pure (am', conn', msg) saveGroupFwdRcvMsg :: (MsgEncodingI e, ChatMonad m) => User -> GroupId -> GroupMember -> GroupMember -> MsgBody -> ChatMessage e -> m RcvMessage -saveGroupFwdRcvMsg user groupId forwardingMember refAuthorMember msgBody ChatMessage {msgId = sharedMsgId_, chatMsgEvent} = do +saveGroupFwdRcvMsg user groupId forwardingMember refAuthorMember@GroupMember {memberId = refMemberId} msgBody ChatMessage {msgId = sharedMsgId_, chatMsgEvent} = do let newMsg = NewRcvMessage {chatMsgEvent, msgBody} fwdMemberId = Just $ groupMemberId' forwardingMember refAuthorId = Just $ groupMemberId' refAuthorMember withStore (\db -> createNewRcvMessage db (GroupId groupId) newMsg sharedMsgId_ refAuthorId fwdMemberId) `catchChatError` \e -> case e of ChatErrorStore (SEDuplicateGroupMessage _ _ (Just authorGroupMemberId) Nothing) -> do - am <- withStore $ \db -> getGroupMember db user groupId authorGroupMemberId - if sameMemberId (memberId (refAuthorMember :: GroupMember)) am + am@GroupMember {memberId = amMemberId} <- withStore $ \db -> getGroupMember db user groupId authorGroupMemberId + if sameMemberId refMemberId am then forM_ (memberConn forwardingMember) $ \fmConn -> - void $ sendDirectMessage fmConn (XGrpMemCon $ memberId (am :: GroupMember)) (GroupId groupId) + void $ sendDirectMessage fmConn (XGrpMemCon amMemberId) (GroupId groupId) else toView $ CRMessageError user "error" "saveGroupFwdRcvMsg: referenced author member id doesn't match message member id" throwError e _ -> throwError e -saveSndChatItem :: ChatMonad m => User -> ChatDirection c 'MDSnd -> SndMessage -> CIContent 'MDSnd -> m (ChatItem c 'MDSnd) +saveSndChatItem :: (ChatMonad m, ChatTypeI c) => User -> ChatDirection c 'MDSnd -> SndMessage -> CIContent 'MDSnd -> m (ChatItem c 'MDSnd) saveSndChatItem user cd msg content = saveSndChatItem' user cd msg content Nothing Nothing Nothing False -saveSndChatItem' :: ChatMonad m => User -> ChatDirection c 'MDSnd -> SndMessage -> CIContent 'MDSnd -> Maybe (CIFile 'MDSnd) -> Maybe (CIQuote c) -> Maybe CITimed -> Bool -> m (ChatItem c 'MDSnd) +saveSndChatItem' :: (ChatMonad m, ChatTypeI c) => User -> ChatDirection c 'MDSnd -> SndMessage -> CIContent 'MDSnd -> Maybe (CIFile 'MDSnd) -> Maybe (CIQuote c) -> Maybe CITimed -> Bool -> m (ChatItem c 'MDSnd) saveSndChatItem' user cd msg@SndMessage {sharedMsgId} content ciFile quotedItem itemTimed live = do createdAt <- liftIO getCurrentTime ciId <- withStore' $ \db -> do @@ -5844,13 +6152,13 @@ saveSndChatItem' user cd msg@SndMessage {sharedMsgId} content ciFile quotedItem ciId <- createNewSndChatItem db user cd msg content quotedItem itemTimed live createdAt forM_ ciFile $ \CIFile {fileId} -> updateFileTransferChatItemId db fileId ciId createdAt pure ciId - liftIO $ mkChatItem cd ciId content ciFile quotedItem (Just sharedMsgId) itemTimed live createdAt Nothing createdAt + pure $ mkChatItem cd ciId content ciFile quotedItem (Just sharedMsgId) itemTimed live createdAt Nothing createdAt -saveRcvChatItem :: ChatMonad m => User -> ChatDirection c 'MDRcv -> RcvMessage -> UTCTime -> CIContent 'MDRcv -> m (ChatItem c 'MDRcv) +saveRcvChatItem :: (ChatMonad m, ChatTypeI c, ChatTypeQuotable c) => User -> ChatDirection c 'MDRcv -> RcvMessage -> UTCTime -> CIContent 'MDRcv -> m (ChatItem c 'MDRcv) saveRcvChatItem user cd msg@RcvMessage {sharedMsgId_} brokerTs content = saveRcvChatItem' user cd msg sharedMsgId_ brokerTs content Nothing Nothing False -saveRcvChatItem' :: ChatMonad m => User -> ChatDirection c 'MDRcv -> RcvMessage -> Maybe SharedMsgId -> UTCTime -> CIContent 'MDRcv -> Maybe (CIFile 'MDRcv) -> Maybe CITimed -> Bool -> m (ChatItem c 'MDRcv) +saveRcvChatItem' :: (ChatMonad m, ChatTypeI c, ChatTypeQuotable c) => User -> ChatDirection c 'MDRcv -> RcvMessage -> Maybe SharedMsgId -> UTCTime -> CIContent 'MDRcv -> Maybe (CIFile 'MDRcv) -> Maybe CITimed -> Bool -> m (ChatItem c 'MDRcv) saveRcvChatItem' user cd msg@RcvMessage {forwardedByMember} sharedMsgId_ brokerTs content ciFile itemTimed live = do createdAt <- liftIO getCurrentTime (ciId, quotedItem) <- withStore' $ \db -> do @@ -5858,14 +6166,14 @@ saveRcvChatItem' user cd msg@RcvMessage {forwardedByMember} sharedMsgId_ brokerT (ciId, quotedItem) <- createNewRcvChatItem db user cd msg sharedMsgId_ content itemTimed live brokerTs createdAt forM_ ciFile $ \CIFile {fileId} -> updateFileTransferChatItemId db fileId ciId createdAt pure (ciId, quotedItem) - liftIO $ mkChatItem cd ciId content ciFile quotedItem sharedMsgId_ itemTimed live brokerTs forwardedByMember createdAt + pure $ mkChatItem cd ciId content ciFile quotedItem sharedMsgId_ itemTimed live brokerTs forwardedByMember createdAt -mkChatItem :: forall c d. MsgDirectionI d => ChatDirection c d -> ChatItemId -> CIContent d -> Maybe (CIFile d) -> Maybe (CIQuote c) -> Maybe SharedMsgId -> Maybe CITimed -> Bool -> ChatItemTs -> Maybe GroupMemberId -> UTCTime -> IO (ChatItem c d) -mkChatItem cd ciId content file quotedItem sharedMsgId itemTimed live itemTs forwardedByMember currentTs = do +mkChatItem :: forall c d. (ChatTypeI c, MsgDirectionI d) => ChatDirection c d -> ChatItemId -> CIContent d -> Maybe (CIFile d) -> Maybe (CIQuote c) -> Maybe SharedMsgId -> Maybe CITimed -> Bool -> ChatItemTs -> Maybe GroupMemberId -> UTCTime -> ChatItem c d +mkChatItem cd ciId content file quotedItem sharedMsgId itemTimed live itemTs forwardedByMember currentTs = let itemText = ciContentToText content itemStatus = ciCreateStatus content meta = mkCIMeta ciId content itemText itemStatus sharedMsgId Nothing False itemTimed (justTrue live) currentTs itemTs forwardedByMember currentTs currentTs - pure ChatItem {chatDir = toCIDirection cd, meta, content, formattedText = parseMaybeMarkdownList itemText, quotedItem, reactions = [], file} + in ChatItem {chatDir = toCIDirection cd, meta, content, formattedText = parseMaybeMarkdownList itemText, quotedItem, reactions = [], file} deleteDirectCI :: (ChatMonad m, MsgDirectionI d) => User -> Contact -> ChatItem 'CTDirect d -> Bool -> Bool -> m ChatResponse deleteDirectCI user ct ci@ChatItem {file} byUser timed = do @@ -5884,6 +6192,14 @@ deleteGroupCI user gInfo ci@ChatItem {file} byUser timed byGroupMember_ deletedT where gItem = AChatItem SCTGroup msgDirection (GroupChat gInfo) +deleteLocalCI :: (ChatMonad m, MsgDirectionI d) => User -> NoteFolder -> ChatItem 'CTLocal d -> Bool -> Bool -> m ChatResponse +deleteLocalCI user nf ci@ChatItem {file} byUser timed = do + forM_ file $ \CIFile {fileSource} -> do + forM_ (CF.filePath <$> fileSource) $ \fPath -> + deleteFileLocally fPath `catchChatError` (toView . CRChatError (Just user)) + withStore' $ \db -> deleteLocalChatItem db user nf ci + pure $ CRChatItemDeleted user (AChatItem SCTLocal msgDirection (LocalChat nf) ci) Nothing byUser timed + deleteCIFile :: (ChatMonad m, MsgDirectionI d) => User -> Maybe (CIFile d) -> m () deleteCIFile user file_ = forM_ file_ $ \file -> do @@ -5960,11 +6276,14 @@ agentXFTPDeleteSndFileRemote user XFTPSndFile {agentSndFileId = AgentSndFileId a withAgent $ \a -> xftpDeleteSndFileRemote a (aUserId user) aFileId sd withStore' $ \db -> setSndFTAgentDeleted db user fileId -userProfileToSend :: User -> Maybe Profile -> Maybe Contact -> Profile -userProfileToSend user@User {profile = p} incognitoProfile ct = +userProfileToSend :: User -> Maybe Profile -> Maybe Contact -> Bool -> Profile +userProfileToSend user@User {profile = p} incognitoProfile ct inGroup = do let p' = fromMaybe (fromLocalProfile p) incognitoProfile - userPrefs = maybe (preferences' user) (const Nothing) incognitoProfile - in (p' :: Profile) {preferences = Just . toChatPrefs $ mergePreferences (userPreferences <$> ct) userPrefs} + if inGroup + then redactedMemberProfile p' + else + let userPrefs = maybe (preferences' user) (const Nothing) incognitoProfile + in (p' :: Profile) {preferences = Just . toChatPrefs $ mergePreferences (userPreferences <$> ct) userPrefs} createRcvFeatureItems :: forall m. ChatMonad m => User -> Contact -> Contact -> m () createRcvFeatureItems user ct ct' = @@ -5974,7 +6293,18 @@ createSndFeatureItems :: forall m. ChatMonad m => User -> Contact -> Contact -> createSndFeatureItems user ct ct' = createFeatureItems user ct ct' CDDirectSnd CISndChatFeature CISndChatPreference getPref where - getPref = (preference :: ContactUserPref (FeaturePreference f) -> FeaturePreference f) . userPreference + getPref ContactUserPreference {userPreference} = case userPreference of + CUPContact {preference} -> preference + CUPUser {preference} -> preference + +createContactsSndFeatureItems :: forall m. ChatMonad m => User -> [ChangedProfileContact] -> m () +createContactsSndFeatureItems user cts = + createContactsFeatureItems user cts' CDDirectSnd CISndChatFeature CISndChatPreference getPref + where + cts' = map (\ChangedProfileContact {ct, ct'} -> (ct, ct')) cts + getPref ContactUserPreference {userPreference} = case userPreference of + CUPContact {preference} -> preference + CUPUser {preference} -> preference type FeatureContent a d = ChatFeature -> a -> Maybe Int -> CIContent d @@ -5989,28 +6319,48 @@ createFeatureItems :: FeatureContent FeatureAllowed d -> (forall f. ContactUserPreference (FeaturePreference f) -> FeaturePreference f) -> m () -createFeatureItems user Contact {mergedPreferences = cups} ct'@Contact {mergedPreferences = cups'} chatDir ciFeature ciOffer getPref = - forM_ allChatFeatures $ \(ACF f) -> createItem f +createFeatureItems user ct ct' = createContactsFeatureItems user [(ct, ct')] + +createContactsFeatureItems :: + forall d m. + (MsgDirectionI d, ChatMonad m) => + User -> + [(Contact, Contact)] -> + (Contact -> ChatDirection 'CTDirect d) -> + FeatureContent PrefEnabled d -> + FeatureContent FeatureAllowed d -> + (forall f. ContactUserPreference (FeaturePreference f) -> FeaturePreference f) -> + m () +createContactsFeatureItems user cts chatDir ciFeature ciOffer getPref = do + let dirsCIContents = map contactChangedFeatures cts + (errs, acis) <- partitionEithers <$> createInternalItemsForChats user Nothing dirsCIContents + unless (null errs) $ toView $ CRChatErrors (Just user) errs + forM_ acis $ \aci -> toView $ CRNewChatItem user aci where - createItem :: forall f. FeatureI f => SChatFeature f -> m () - createItem f - | state /= state' = create ciFeature state' - | prefState /= prefState' = create ciOffer prefState' - | otherwise = pure () + contactChangedFeatures :: (Contact, Contact) -> (ChatDirection 'CTDirect d, [CIContent d]) + contactChangedFeatures (Contact {mergedPreferences = cups}, ct'@Contact {mergedPreferences = cups'}) = do + let contents = mapMaybe (\(ACF f) -> featureCIContent_ f) allChatFeatures + (chatDir ct', contents) where - create :: FeatureContent a d -> (a, Maybe Int) -> m () - create ci (s, param) = createInternalChatItem user (chatDir ct') (ci f' s param) Nothing - f' = chatFeature f - state = featureState cup - state' = featureState cup' - prefState = preferenceState $ getPref cup - prefState' = preferenceState $ getPref cup' - cup = getContactUserPreference f cups - cup' = getContactUserPreference f cups' + featureCIContent_ :: forall f. FeatureI f => SChatFeature f -> Maybe (CIContent d) + featureCIContent_ f + | state /= state' = Just $ fContent ciFeature state' + | prefState /= prefState' = Just $ fContent ciOffer prefState' + | otherwise = Nothing + where + fContent :: FeatureContent a d -> (a, Maybe Int) -> CIContent d + fContent ci (s, param) = ci f' s param + f' = chatFeature f + state = featureState cup + state' = featureState cup' + prefState = preferenceState $ getPref cup + prefState' = preferenceState $ getPref cup' + cup = getContactUserPreference f cups + cup' = getContactUserPreference f cups' createGroupFeatureChangedItems :: (MsgDirectionI d, ChatMonad m) => User -> ChatDirection 'CTGroup d -> (GroupFeature -> GroupPreference -> Maybe Int -> CIContent d) -> GroupInfo -> GroupInfo -> m () createGroupFeatureChangedItems user cd ciContent GroupInfo {fullGroupPreferences = gps} GroupInfo {fullGroupPreferences = gps'} = - forM_ allGroupFeatureItems $ \(AGF f) -> do + forM_ allGroupFeatures $ \(AGF f) -> do let state = groupFeatureState $ getGroupPreference f gps pref' = getGroupPreference f gps' state'@(_, int') = groupFeatureState pref' @@ -6020,75 +6370,44 @@ createGroupFeatureChangedItems user cd ciContent GroupInfo {fullGroupPreferences sameGroupProfileInfo :: GroupProfile -> GroupProfile -> Bool sameGroupProfileInfo p p' = p {groupPreferences = Nothing} == p' {groupPreferences = Nothing} -createInternalChatItem :: forall c d m. (ChatTypeI c, MsgDirectionI d, ChatMonad m) => User -> ChatDirection c d -> CIContent d -> Maybe UTCTime -> m () -createInternalChatItem user cd content itemTs_ = do +createInternalChatItem :: (ChatTypeI c, MsgDirectionI d, ChatMonad m) => User -> ChatDirection c d -> CIContent d -> Maybe UTCTime -> m () +createInternalChatItem user cd content itemTs_ = + createInternalItemsForChats user itemTs_ [(cd, [content])] >>= \case + [Right aci] -> toView $ CRNewChatItem user aci + [Left e] -> throwError e + rs -> throwChatError $ CEInternalError $ "createInternalChatItem: expected 1 result, got " <> show (length rs) + +createInternalItemsForChats :: + forall c d m. + (ChatTypeI c, MsgDirectionI d, ChatMonad' m) => + User -> + Maybe UTCTime -> + [(ChatDirection c d, [CIContent d])] -> + m [Either ChatError AChatItem] +createInternalItemsForChats user itemTs_ dirsCIContents = do createdAt <- liftIO getCurrentTime let itemTs = fromMaybe createdAt itemTs_ - ciId <- withStore' $ \db -> do - when (ciRequiresAttention content) $ updateChatTs db user cd createdAt - createNewChatItemNoMsg db user cd content itemTs createdAt - ci <- liftIO $ mkChatItem cd ciId content Nothing Nothing Nothing Nothing False itemTs Nothing createdAt - toView $ CRNewChatItem user (AChatItem (chatTypeI @c) (msgDirection @d) (toChatInfo cd) ci) - -getCreateActiveUser :: SQLiteStore -> Bool -> IO User -getCreateActiveUser st testView = do - user <- - withTransaction st getUsers >>= \case - [] -> newUser - users -> maybe (selectUser users) pure (find activeUser users) - unless testView $ putStrLn $ "Current user: " <> userStr user - pure user + void . withStoreBatch' $ \db -> map (uncurry $ updateChat db createdAt) dirsCIContents + withStoreBatch' $ \db -> concatMap (uncurry $ createACIs db itemTs createdAt) dirsCIContents where - newUser :: IO User - newUser = do - putStrLn - "No user profiles found, it will be created now.\n\ - \Please choose your display name and your full name.\n\ - \They will be sent to your contacts when you connect.\n\ - \They are only stored on your device and you can change them later." - loop - where - loop = do - displayName <- getContactName - withTransaction st (\db -> runExceptT $ createUserRecord db (AgentUserId 1) (profileFromName displayName) True) >>= \case - Left SEDuplicateName -> do - putStrLn "chosen display name is already used by another profile on this device, choose another one" - loop - Left e -> putStrLn ("database error " <> show e) >> exitFailure - Right user -> pure user - selectUser :: [User] -> IO User - selectUser [user] = do - withTransaction st (`setActiveUser` userId (user :: User)) - pure user - selectUser users = do - putStrLn "Select user profile:" - forM_ (zip [1 ..] users) $ \(n :: Int, user) -> putStrLn $ show n <> " - " <> userStr user - loop - where - loop = do - nStr <- getWithPrompt $ "user profile number (1 .. " <> show (length users) <> ")" - case readMaybe nStr :: Maybe Int of - Nothing -> putStrLn "invalid user number" >> loop - Just n - | n <= 0 || n > length users -> putStrLn "invalid user number" >> loop - | otherwise -> do - let user = users !! (n - 1) - withTransaction st (`setActiveUser` userId (user :: User)) - pure user - userStr :: User -> String - userStr User {localDisplayName, profile = LocalProfile {fullName}} = - T.unpack $ localDisplayName <> if T.null fullName || localDisplayName == fullName then "" else " (" <> fullName <> ")" - getContactName :: IO ContactName - getContactName = do - displayName <- getWithPrompt "display name" - let validName = mkValidName displayName - if - | null displayName -> putStrLn "display name can't be empty" >> getContactName - | null validName -> putStrLn "display name is invalid, please choose another" >> getContactName - | displayName /= validName -> putStrLn ("display name is invalid, you could use this one: " <> validName) >> getContactName - | otherwise -> pure $ T.pack displayName - getWithPrompt :: String -> IO String - getWithPrompt s = putStr (s <> ": ") >> hFlush stdout >> getLine + updateChat :: DB.Connection -> UTCTime -> ChatDirection c d -> [CIContent d] -> IO () + updateChat db createdAt cd contents + | any ciRequiresAttention contents = updateChatTs db user cd createdAt + | otherwise = pure () + createACIs :: DB.Connection -> UTCTime -> UTCTime -> ChatDirection c d -> [CIContent d] -> [IO AChatItem] + createACIs db itemTs createdAt cd = map $ \content -> do + ciId <- createNewChatItemNoMsg db user cd content itemTs createdAt + let ci = mkChatItem cd ciId content Nothing Nothing Nothing Nothing False itemTs Nothing createdAt + pure $ AChatItem (chatTypeI @c) (msgDirection @d) (toChatInfo cd) ci + +createLocalChatItem :: (MsgDirectionI d, ChatMonad m) => User -> ChatDirection 'CTLocal d -> CIContent d -> UTCTime -> m ChatItemId +createLocalChatItem user cd content createdAt = do + gVar <- asks random + withStore $ \db -> do + liftIO $ updateChatTs db user cd createdAt + createWithRandomId gVar $ \sharedMsgId -> + let smi_ = Just (SharedMsgId sharedMsgId) + in createNewChatItem_ db user cd Nothing smi_ content (Nothing, Nothing, Nothing, Nothing, Nothing) Nothing False createdAt Nothing createdAt withUser' :: ChatMonad m => (User -> m ChatResponse) -> m ChatResponse withUser' action = @@ -6201,6 +6520,7 @@ chatCommandP = "/_get items " *> (APIGetChatItems <$> chatPaginationP <*> optional (" search=" *> stringP)), "/_get item info " *> (APIGetChatItemInfo <$> chatRefP <* A.space <*> A.decimal), "/_send " *> (APISendMessage <$> chatRefP <*> liveMessageP <*> sendMessageTTLP <*> (" json " *> jsonP <|> " text " *> (ComposedMessage Nothing Nothing <$> mcTextP))), + "/_create *" *> (APICreateChatItem <$> A.decimal <*> (" json " *> jsonP <|> " text " *> (ComposedMessage Nothing Nothing <$> mcTextP))), "/_update item " *> (APIUpdateChatItem <$> chatRefP <* A.space <*> A.decimal <*> liveMessageP <* A.space <*> msgContentP), "/_delete item " *> (APIDeleteChatItem <$> chatRefP <* A.space <*> A.decimal <* A.space <*> ciDeleteMode), "/_delete member item #" *> (APIDeleteMemberChatItem <$> A.decimal <* A.space <*> A.decimal <* A.space <*> A.decimal), @@ -6236,6 +6556,7 @@ chatCommandP = "/_add #" *> (APIAddMember <$> A.decimal <* A.space <*> A.decimal <*> memberRole), "/_join #" *> (APIJoinGroup <$> A.decimal), "/_member role #" *> (APIMemberRole <$> A.decimal <* A.space <*> A.decimal <*> memberRole), + "/_block #" *> (APIBlockMemberForAll <$> A.decimal <* A.space <*> A.decimal <* A.space <* "blocked=" <*> onOffP), "/_remove #" *> (APIRemoveMember <$> A.decimal <* A.space <*> A.decimal), "/_leave #" *> (APILeaveGroup <$> A.decimal), "/_members #" *> (APIListMembers <$> A.decimal), @@ -6305,10 +6626,13 @@ chatCommandP = ("/add " <|> "/a ") *> char_ '#' *> (AddMember <$> displayName <* A.space <* char_ '@' <*> displayName <*> (memberRole <|> pure GRMember)), ("/join " <|> "/j ") *> char_ '#' *> (JoinGroup <$> displayName), ("/member role " <|> "/mr ") *> char_ '#' *> (MemberRole <$> displayName <* A.space <* char_ '@' <*> displayName <*> memberRole), + "/block for all #" *> (BlockForAll <$> displayName <* A.space <*> (char_ '@' *> displayName) <*> pure True), + "/unblock for all #" *> (BlockForAll <$> displayName <* A.space <*> (char_ '@' *> displayName) <*> pure False), ("/remove " <|> "/rm ") *> char_ '#' *> (RemoveMember <$> displayName <* A.space <* char_ '@' <*> displayName), ("/leave " <|> "/l ") *> char_ '#' *> (LeaveGroup <$> displayName), ("/delete #" <|> "/d #") *> (DeleteGroup <$> displayName), ("/delete " <|> "/d ") *> char_ '@' *> (DeleteContact <$> displayName), + "/clear *" $> ClearNoteFolder, "/clear #" *> (ClearGroup <$> displayName), "/clear " *> char_ '@' *> (ClearContact <$> displayName), ("/members " <|> "/ms ") *> char_ '#' *> (ListMembers <$> displayName), @@ -6342,6 +6666,7 @@ chatCommandP = ("/connect" <|> "/c") *> (Connect <$> incognitoP <* A.space <*> ((Just <$> strP) <|> A.takeTill isSpace $> Nothing)), ("/connect" <|> "/c") *> (AddContact <$> incognitoP), SendMessage <$> chatNameP <* A.space <*> msgTextP, + "/* " *> (SendMessage (ChatName CTLocal "") <$> msgTextP), "@#" *> (SendMemberContactMessage <$> displayName <* A.space <* char_ '@' <*> displayName <* A.space <*> msgTextP), "/live " *> (SendLiveMessage <$> chatNameP <*> (A.space *> msgTextP <|> pure "")), (">@" <|> "> @") *> sendMsgQuote (AMsgDirection SMDRcv), @@ -6411,7 +6736,7 @@ chatCommandP = "/delete remote host " *> (DeleteRemoteHost <$> A.decimal), "/store remote file " *> (StoreRemoteFile <$> A.decimal <*> optional (" encrypt=" *> onOffP) <* A.space <*> filePath), "/get remote file " *> (GetRemoteFile <$> A.decimal <* A.space <*> jsonP), - "/connect remote ctrl " *> (ConnectRemoteCtrl <$> strP), + ("/connect remote ctrl " <|> "/crc ") *> (ConnectRemoteCtrl <$> strP), "/find remote ctrl" $> FindKnownRemoteCtrl, "/confirm remote ctrl " *> (ConfirmRemoteCtrl <$> A.decimal), "/verify remote ctrl " *> (VerifyRemoteCtrlSession <$> textP), @@ -6424,7 +6749,9 @@ chatCommandP = "/get stats" $> GetAgentStats, "/reset stats" $> ResetAgentStats, "/get subs" $> GetAgentSubs, - "/get subs details" $> GetAgentSubsDetails + "/get subs details" $> GetAgentSubsDetails, + "/get workers" $> GetAgentWorkers, + "/get workers details" $> GetAgentWorkersDetails ] where choice = A.choice . map (\p -> p <* A.takeWhile (== ' ') <* A.endOfInput) @@ -6432,7 +6759,7 @@ chatCommandP = incognitoOnOffP = (A.space *> "incognito=" *> onOffP) <|> pure False imagePrefix = (<>) <$> "data:" <*> ("image/png;base64," <|> "image/jpg;base64,") imageP = safeDecodeUtf8 <$> ((<>) <$> imagePrefix <*> (B64.encode <$> base64P)) - chatTypeP = A.char '@' $> CTDirect <|> A.char '#' $> CTGroup <|> A.char ':' $> CTContactConnection + chatTypeP = A.char '@' $> CTDirect <|> A.char '#' $> CTGroup <|> A.char '*' $> CTLocal <|> A.char ':' $> CTContactConnection chatPaginationP = (CPLast <$ "count=" <*> A.decimal) <|> (CPAfter <$ "after=" <*> A.decimal <* A.space <* "count=" <*> A.decimal) @@ -6505,7 +6832,10 @@ chatCommandP = " member" $> GRMember, " observer" $> GRObserver ] - chatNameP = ChatName <$> chatTypeP <*> displayName + chatNameP = + chatTypeP >>= \case + CTLocal -> pure $ ChatName CTLocal "" + ct -> ChatName ct <$> displayName chatNameP' = ChatName <$> (chatTypeP <|> pure CTDirect) <*> displayName chatRefP = ChatRef <$> chatTypeP <*> A.decimal msgCountP = A.space *> A.decimal <|> pure 10 @@ -6555,7 +6885,7 @@ chatCommandP = (pure Nothing) srvCfgP = strP >>= \case AProtocolType p -> APSC p <$> (A.space *> jsonP) toServerCfg server = ServerCfg {server, preset = False, tested = Nothing, enabled = True} - rcCtrlAddressP = RCCtrlAddress <$> ("addr=" *> strP) <*> (" iface=" *> text1P) + rcCtrlAddressP = RCCtrlAddress <$> ("addr=" *> strP) <*> (" iface=" *> (jsonP <|> text1P)) text1P = safeDecodeUtf8 <$> A.takeTill (== ' ') char_ = optional . A.char diff --git a/src/Simplex/Chat/Bot.hs b/src/Simplex/Chat/Bot.hs index 3f7e2c2f09..c5c5ff7eed 100644 --- a/src/Simplex/Chat/Bot.hs +++ b/src/Simplex/Chat/Bot.hs @@ -9,7 +9,6 @@ module Simplex.Chat.Bot where import Control.Concurrent.Async import Control.Concurrent.STM import Control.Monad -import Control.Monad.Reader import qualified Data.ByteString.Char8 as B import qualified Data.Text as T import Simplex.Chat.Controller diff --git a/src/Simplex/Chat/Controller.hs b/src/Simplex/Chat/Controller.hs index faf3a21a03..d3c8698f94 100644 --- a/src/Simplex/Chat/Controller.hs +++ b/src/Simplex/Chat/Controller.hs @@ -60,7 +60,7 @@ import Simplex.Chat.Store (AutoAccept, StoreError (..), UserContactLink, UserMsg import Simplex.Chat.Types import Simplex.Chat.Types.Preferences import Simplex.Messaging.Agent (AgentClient, SubscriptionsInfo) -import Simplex.Messaging.Agent.Client (AgentLocks, ProtocolTestFailure) +import Simplex.Messaging.Agent.Client (AgentLocks, AgentWorkersDetails (..), AgentWorkersSummary (..), ProtocolTestFailure) import Simplex.Messaging.Agent.Env.SQLite (AgentConfig, NetworkConfig) import Simplex.Messaging.Agent.Lock import Simplex.Messaging.Agent.Protocol @@ -258,6 +258,7 @@ data ChatCommand | APIGetChatItems ChatPagination (Maybe String) | APIGetChatItemInfo ChatRef ChatItemId | APISendMessage {chatRef :: ChatRef, liveMessage :: Bool, ttl :: Maybe Int, composedMessage :: ComposedMessage} + | APICreateChatItem {noteFolderId :: NoteFolderId, composedMessage :: ComposedMessage} | APIUpdateChatItem {chatRef :: ChatRef, chatItemId :: ChatItemId, liveMessage :: Bool, msgContent :: MsgContent} | APIDeleteChatItem ChatRef ChatItemId CIDeleteMode | APIDeleteMemberChatItem GroupId GroupMemberId ChatItemId @@ -293,6 +294,7 @@ data ChatCommand | APIAddMember GroupId ContactId GroupMemberRole | APIJoinGroup GroupId | APIMemberRole GroupId GroupMemberId GroupMemberRole + | APIBlockMemberForAll GroupId GroupMemberId Bool | APIRemoveMember GroupId GroupMemberId | APILeaveGroup GroupId | APIListMembers GroupId @@ -392,6 +394,7 @@ data ChatCommand | AddMember GroupName ContactName GroupMemberRole | JoinGroup GroupName | MemberRole GroupName ContactName GroupMemberRole + | BlockForAll GroupName ContactName Bool | RemoveMember GroupName ContactName | LeaveGroup GroupName | DeleteGroup GroupName @@ -408,6 +411,7 @@ data ChatCommand | DeleteGroupLink GroupName | ShowGroupLink GroupName | SendGroupMessageQuote {groupName :: GroupName, contactName_ :: Maybe ContactName, quotedMsg :: Text, message :: Text} + | ClearNoteFolder | LastChats (Maybe Int) -- UserId (not used in UI) | LastMessages (Maybe ChatName) Int (Maybe String) -- UserId (not used in UI) | LastChatItemId (Maybe ChatName) Int -- UserId (not used in UI) @@ -455,6 +459,8 @@ data ChatCommand | ResetAgentStats | GetAgentSubs | GetAgentSubsDetails + | GetAgentWorkers + | GetAgentWorkersDetails deriving (Show) allowRemoteCommand :: ChatCommand -> Bool -- XXX: consider using Relay/Block/ForceLocal @@ -626,10 +632,15 @@ data ChatResponse | CRJoinedGroupMemberConnecting {user :: User, groupInfo :: GroupInfo, hostMember :: GroupMember, member :: GroupMember} | CRMemberRole {user :: User, groupInfo :: GroupInfo, byMember :: GroupMember, member :: GroupMember, fromRole :: GroupMemberRole, toRole :: GroupMemberRole} | CRMemberRoleUser {user :: User, groupInfo :: GroupInfo, member :: GroupMember, fromRole :: GroupMemberRole, toRole :: GroupMemberRole} + | CRMemberBlockedForAll {user :: User, groupInfo :: GroupInfo, byMember :: GroupMember, member :: GroupMember, blocked :: Bool} + | CRMemberBlockedForAllUser {user :: User, groupInfo :: GroupInfo, member :: GroupMember, blocked :: Bool} | CRConnectedToGroupMember {user :: User, groupInfo :: GroupInfo, member :: GroupMember, memberContact :: Maybe Contact} | CRDeletedMember {user :: User, groupInfo :: GroupInfo, byMember :: GroupMember, deletedMember :: GroupMember} | CRDeletedMemberUser {user :: User, groupInfo :: GroupInfo, member :: GroupMember} | CRLeftMember {user :: User, groupInfo :: GroupInfo, member :: GroupMember} + | CRUnknownMemberCreated {user :: User, groupInfo :: GroupInfo, forwardedByMember :: GroupMember, member :: GroupMember} + | CRUnknownMemberBlocked {user :: User, groupInfo :: GroupInfo, blockedByMember :: GroupMember, member :: GroupMember} + | CRUnknownMemberAnnounced {user :: User, groupInfo :: GroupInfo, announcingMember :: GroupMember, unknownMember :: GroupMember, announcedMember :: GroupMember} | CRGroupEmpty {user :: User, groupInfo :: GroupInfo} | CRGroupRemoved {user :: User, groupInfo :: GroupInfo} | CRGroupDeleted {user :: User, groupInfo :: GroupInfo, member :: GroupMember} @@ -683,6 +694,8 @@ data ChatResponse | CRSlowSQLQueries {chatQueries :: [SlowSQLQuery], agentQueries :: [SlowSQLQuery]} | CRDebugLocks {chatLockName :: Maybe String, agentLocks :: AgentLocks} | CRAgentStats {agentStats :: [[String]]} + | CRAgentWorkersDetails {agentWorkersDetails :: AgentWorkersDetails} + | CRAgentWorkersSummary {agentWorkersSummary :: AgentWorkersSummary} | CRAgentSubs {activeSubs :: Map Text Int, pendingSubs :: Map Text Int, removedSubs :: Map Text [String]} | CRAgentSubsDetails {agentSubs :: SubscriptionsInfo} | CRConnectionDisabled {connectionEntity :: ConnectionEntity} @@ -895,8 +908,7 @@ data PendingSubStatus = PendingSubStatus deriving (Show) data UserProfileUpdateSummary = UserProfileUpdateSummary - { notChanged :: Int, - updateSuccesses :: Int, + { updateSuccesses :: Int, updateFailures :: Int, changedContacts :: [Contact] } @@ -1046,6 +1058,7 @@ data ChatErrorType | CEGroupDuplicateMemberId | CEGroupNotJoined {groupInfo :: GroupInfo} | CEGroupMemberNotActive + | CECantBlockMemberForSelf {groupInfo :: GroupInfo, member :: GroupMember, setShowMessages :: Bool} | CEGroupMemberUserRemoved | CEGroupMemberNotFound | CEGroupMemberIntroNotFound {contactName :: ContactName} diff --git a/src/Simplex/Chat/Core.hs b/src/Simplex/Chat/Core.hs index 0444723de4..a8580746d1 100644 --- a/src/Simplex/Chat/Core.hs +++ b/src/Simplex/Chat/Core.hs @@ -1,17 +1,34 @@ {-# LANGUAGE DuplicateRecordFields #-} +{-# LANGUAGE LambdaCase #-} {-# LANGUAGE NamedFieldPuns #-} +{-# LANGUAGE OverloadedStrings #-} -module Simplex.Chat.Core where +module Simplex.Chat.Core + ( simplexChatCore, + runSimplexChat, + sendChatCmdStr, + sendChatCmd, + ) +where import Control.Logger.Simple +import Control.Monad import Control.Monad.Reader +import Data.List (find) import qualified Data.Text as T import Data.Text.Encoding (encodeUtf8) +import Data.Time.Clock (getCurrentTime) +import Data.Time.LocalTime (getCurrentTimeZone) import Simplex.Chat import Simplex.Chat.Controller import Simplex.Chat.Options (ChatOpts (..), CoreChatOpts (..)) +import Simplex.Chat.Store.Profiles import Simplex.Chat.Types +import Simplex.Chat.View (serializeChatResponse) +import Simplex.Messaging.Agent.Store.SQLite (SQLiteStore, withTransaction) import System.Exit (exitFailure) +import System.IO (hFlush, stdout) +import Text.Read (readMaybe) import UnliftIO.Async simplexChatCore :: ChatConfig -> ChatOpts -> (User -> ChatController -> IO ()) -> IO () @@ -27,8 +44,10 @@ simplexChatCore cfg@ChatConfig {confirmMigrations, testView} opts@ChatOpts {core putStrLn $ "Error opening database: " <> show e exitFailure run db@ChatDatabase {chatStore} = do - u <- getCreateActiveUser chatStore testView - cc <- newChatController db (Just u) cfg opts False + u_ <- getSelectActiveUser chatStore + cc <- newChatController db u_ cfg opts False + u <- maybe (createActiveUser cc) pure u_ + unless testView $ putStrLn $ "Current user: " <> userStr u runSimplexChat opts u cc chat runSimplexChat :: ChatOpts -> User -> ChatController -> (User -> ChatController -> IO ()) -> IO () @@ -44,3 +63,59 @@ sendChatCmdStr cc s = runReaderT (execChatCommand Nothing . encodeUtf8 $ T.pack sendChatCmd :: ChatController -> ChatCommand -> IO ChatResponse sendChatCmd cc cmd = runReaderT (execChatCommand' cmd) cc + +getSelectActiveUser :: SQLiteStore -> IO (Maybe User) +getSelectActiveUser st = do + users <- withTransaction st getUsers + case find activeUser users of + Just u -> pure $ Just u + Nothing -> selectUser users + where + selectUser :: [User] -> IO (Maybe User) + selectUser = \case + [] -> pure Nothing + [user@User {userId}] -> do + withTransaction st (`setActiveUser` userId) + pure $ Just user + users -> do + putStrLn "Select user profile:" + forM_ (zip [1 :: Int ..] users) $ \(n, user) -> putStrLn $ show n <> ": " <> userStr user + loop + where + loop = do + nStr <- getWithPrompt $ "user number (1 .. " <> show (length users) <> ")" + case readMaybe nStr :: Maybe Int of + Nothing -> putStrLn "not a number" >> loop + Just n + | n <= 0 || n > length users -> putStrLn "invalid user number" >> loop + | otherwise -> do + let user@User {userId} = users !! (n - 1) + withTransaction st (`setActiveUser` userId) + pure $ Just user + +createActiveUser :: ChatController -> IO User +createActiveUser cc = do + putStrLn + "No user profiles found, it will be created now.\n\ + \Please choose your display name.\n\ + \It will be sent to your contacts when you connect.\n\ + \It is only stored on your device and you can change it later." + loop + where + loop = do + displayName <- T.pack <$> getWithPrompt "display name" + let profile = Just Profile {displayName, fullName = "", image = Nothing, contactLink = Nothing, preferences = Nothing} + execChatCommand' (CreateActiveUser NewUser {profile, sameServers = False, pastTimestamp = False}) `runReaderT` cc >>= \case + CRActiveUser user -> pure user + r -> do + ts <- getCurrentTime + tz <- getCurrentTimeZone + putStrLn $ serializeChatResponse (Nothing, Nothing) ts tz Nothing r + loop + +getWithPrompt :: String -> IO String +getWithPrompt s = putStr (s <> ": ") >> hFlush stdout >> getLine + +userStr :: User -> String +userStr User {localDisplayName, profile = LocalProfile {fullName}} = + T.unpack $ localDisplayName <> if T.null fullName || localDisplayName == fullName then "" else " (" <> fullName <> ")" diff --git a/src/Simplex/Chat/Messages.hs b/src/Simplex/Chat/Messages.hs index cdd1931039..50b098bb71 100644 --- a/src/Simplex/Chat/Messages.hs +++ b/src/Simplex/Chat/Messages.hs @@ -10,11 +10,15 @@ {-# LANGUAGE StandaloneDeriving #-} {-# LANGUAGE TemplateHaskell #-} {-# LANGUAGE TypeApplications #-} +{-# LANGUAGE TypeFamilies #-} +{-# LANGUAGE TypeOperators #-} +{-# LANGUAGE UndecidableInstances #-} {-# OPTIONS_GHC -fno-warn-ambiguous-fields #-} module Simplex.Chat.Messages where import Control.Applicative ((<|>)) +import Control.Monad ((>=>)) import Data.Aeson (FromJSON, ToJSON, (.:)) import qualified Data.Aeson as J import qualified Data.Aeson.Encoding as JE @@ -24,6 +28,7 @@ import qualified Data.ByteString.Base64 as B64 import qualified Data.ByteString.Lazy.Char8 as LB import Data.Char (isSpace) import Data.Int (Int64) +import Data.Kind (Constraint) import Data.Maybe (fromMaybe, isJust, isNothing) import Data.Text (Text) import qualified Data.Text as T @@ -33,6 +38,8 @@ import Data.Type.Equality import Data.Typeable (Typeable) import Database.SQLite.Simple.FromField (FromField (..)) import Database.SQLite.Simple.ToField (ToField (..)) +import GHC.TypeLits (ErrorMessage (ShowType, type (:<>:)), TypeError) +import qualified GHC.TypeLits as Type import Simplex.Chat.Markdown import Simplex.Chat.Messages.CIContent import Simplex.Chat.Protocol @@ -46,7 +53,7 @@ import Simplex.Messaging.Parsers (defaultJSON, dropPrefix, enumJSON, fromTextFie import Simplex.Messaging.Protocol (MsgBody) import Simplex.Messaging.Util (eitherToMaybe, safeDecodeUtf8, (<$?>)) -data ChatType = CTDirect | CTGroup | CTContactRequest | CTContactConnection +data ChatType = CTDirect | CTGroup | CTLocal | CTContactRequest | CTContactConnection deriving (Eq, Show, Ord) data ChatName = ChatName {chatType :: ChatType, chatName :: Text} @@ -56,6 +63,7 @@ chatTypeStr :: ChatType -> Text chatTypeStr = \case CTDirect -> "@" CTGroup -> "#" + CTLocal -> "*" CTContactRequest -> "<@" CTContactConnection -> ":" @@ -68,6 +76,7 @@ data ChatRef = ChatRef ChatType Int64 data ChatInfo (c :: ChatType) where DirectChat :: Contact -> ChatInfo 'CTDirect GroupChat :: GroupInfo -> ChatInfo 'CTGroup + LocalChat :: NoteFolder -> ChatInfo 'CTLocal ContactRequest :: UserContactRequest -> ChatInfo 'CTContactRequest ContactConnection :: PendingContactConnection -> ChatInfo 'CTContactConnection @@ -83,6 +92,7 @@ chatInfoUpdatedAt :: ChatInfo c -> UTCTime chatInfoUpdatedAt = \case DirectChat Contact {updatedAt} -> updatedAt GroupChat GroupInfo {updatedAt} -> updatedAt + LocalChat NoteFolder {updatedAt} -> updatedAt ContactRequest UserContactRequest {updatedAt} -> updatedAt ContactConnection PendingContactConnection {updatedAt} -> updatedAt @@ -90,6 +100,7 @@ chatInfoToRef :: ChatInfo c -> ChatRef chatInfoToRef = \case DirectChat Contact {contactId} -> ChatRef CTDirect contactId GroupChat GroupInfo {groupId} -> ChatRef CTGroup groupId + LocalChat NoteFolder {noteFolderId} -> ChatRef CTLocal noteFolderId ContactRequest UserContactRequest {contactRequestId} -> ChatRef CTContactRequest contactRequestId ContactConnection PendingContactConnection {pccConnId} -> ChatRef CTContactConnection pccConnId @@ -101,6 +112,7 @@ chatInfoMembership = \case data JSONChatInfo = JCInfoDirect {contact :: Contact} | JCInfoGroup {groupInfo :: GroupInfo} + | JCInfoLocal {noteFolder :: NoteFolder} | JCInfoContactRequest {contactRequest :: UserContactRequest} | JCInfoContactConnection {contactConnection :: PendingContactConnection} @@ -117,6 +129,7 @@ jsonChatInfo :: ChatInfo c -> JSONChatInfo jsonChatInfo = \case DirectChat c -> JCInfoDirect c GroupChat g -> JCInfoGroup g + LocalChat l -> JCInfoLocal l ContactRequest g -> JCInfoContactRequest g ContactConnection c -> JCInfoContactConnection c @@ -128,6 +141,7 @@ jsonAChatInfo :: JSONChatInfo -> AChatInfo jsonAChatInfo = \case JCInfoDirect c -> AChatInfo SCTDirect $ DirectChat c JCInfoGroup g -> AChatInfo SCTGroup $ GroupChat g + JCInfoLocal l -> AChatInfo SCTLocal $ LocalChat l JCInfoContactRequest g -> AChatInfo SCTContactRequest $ ContactRequest g JCInfoContactConnection c -> AChatInfo SCTContactConnection $ ContactConnection c @@ -167,6 +181,8 @@ data CIDirection (c :: ChatType) (d :: MsgDirection) where CIDirectRcv :: CIDirection 'CTDirect 'MDRcv CIGroupSnd :: CIDirection 'CTGroup 'MDSnd CIGroupRcv :: GroupMember -> CIDirection 'CTGroup 'MDRcv + CILocalSnd :: CIDirection 'CTLocal 'MDSnd + CILocalRcv :: CIDirection 'CTLocal 'MDRcv deriving instance Show (CIDirection c d) @@ -179,6 +195,8 @@ data JSONCIDirection | JCIDirectRcv | JCIGroupSnd | JCIGroupRcv {groupMember :: GroupMember} + | JCILocalSnd + | JCILocalRcv deriving (Show) jsonCIDirection :: CIDirection c d -> JSONCIDirection @@ -187,6 +205,8 @@ jsonCIDirection = \case CIDirectRcv -> JCIDirectRcv CIGroupSnd -> JCIGroupSnd CIGroupRcv m -> JCIGroupRcv m + CILocalSnd -> JCILocalSnd + CILocalRcv -> JCILocalRcv jsonACIDirection :: JSONCIDirection -> ACIDirection jsonACIDirection = \case @@ -194,6 +214,8 @@ jsonACIDirection = \case JCIDirectRcv -> ACID SCTDirect SMDRcv CIDirectRcv JCIGroupSnd -> ACID SCTGroup SMDSnd CIGroupSnd JCIGroupRcv m -> ACID SCTGroup SMDRcv $ CIGroupRcv m + JCILocalSnd -> ACID SCTLocal SMDSnd CILocalSnd + JCILocalRcv -> ACID SCTLocal SMDRcv CILocalRcv data CIReactionCount = CIReactionCount {reaction :: MsgReaction, userReacted :: Bool, totalReacted :: Int} deriving (Show) @@ -234,6 +256,8 @@ data ChatDirection (c :: ChatType) (d :: MsgDirection) where CDDirectRcv :: Contact -> ChatDirection 'CTDirect 'MDRcv CDGroupSnd :: GroupInfo -> ChatDirection 'CTGroup 'MDSnd CDGroupRcv :: GroupInfo -> GroupMember -> ChatDirection 'CTGroup 'MDRcv + CDLocalSnd :: NoteFolder -> ChatDirection 'CTLocal 'MDSnd + CDLocalRcv :: NoteFolder -> ChatDirection 'CTLocal 'MDRcv toCIDirection :: ChatDirection c d -> CIDirection c d toCIDirection = \case @@ -241,6 +265,8 @@ toCIDirection = \case CDDirectRcv _ -> CIDirectRcv CDGroupSnd _ -> CIGroupSnd CDGroupRcv _ m -> CIGroupRcv m + CDLocalSnd _ -> CILocalSnd + CDLocalRcv _ -> CILocalRcv toChatInfo :: ChatDirection c d -> ChatInfo c toChatInfo = \case @@ -248,6 +274,8 @@ toChatInfo = \case CDDirectRcv c -> DirectChat c CDGroupSnd g -> GroupChat g CDGroupRcv g _ -> GroupChat g + CDLocalSnd l -> LocalChat l + CDLocalRcv l -> LocalChat l data NewChatItem d = NewChatItem { createdByMsgId :: Maybe MessageId, @@ -322,10 +350,13 @@ data CIMeta (c :: ChatType) (d :: MsgDirection) = CIMeta } deriving (Show) -mkCIMeta :: ChatItemId -> CIContent d -> Text -> CIStatus d -> Maybe SharedMsgId -> Maybe (CIDeleted c) -> Bool -> Maybe CITimed -> Maybe Bool -> UTCTime -> ChatItemTs -> Maybe GroupMemberId -> UTCTime -> UTCTime -> CIMeta c d +mkCIMeta :: forall c d. ChatTypeI c => ChatItemId -> CIContent d -> Text -> CIStatus d -> Maybe SharedMsgId -> Maybe (CIDeleted c) -> Bool -> Maybe CITimed -> Maybe Bool -> UTCTime -> ChatItemTs -> Maybe GroupMemberId -> UTCTime -> UTCTime -> CIMeta c d mkCIMeta itemId itemContent itemText itemStatus itemSharedMsgId itemDeleted itemEdited itemTimed itemLive currentTs itemTs forwardedByMember createdAt updatedAt = let editable = case itemContent of - CISndMsgContent _ -> diffUTCTime currentTs itemTs < nominalDay && isNothing itemDeleted + CISndMsgContent _ -> + case chatTypeI @c of + SCTLocal -> isNothing itemDeleted + _ -> diffUTCTime currentTs itemTs < nominalDay && isNothing itemDeleted _ -> False in CIMeta {itemId, itemTs, itemText, itemStatus, itemSharedMsgId, itemDeleted, itemEdited, itemTimed, itemLive, editable, forwardedByMember, createdAt, updatedAt} @@ -343,7 +374,9 @@ contactTimedTTL Contact {mergedPreferences = ContactUserPreferences {timedMessag | forUser enabled && forContact enabled = Just ttl | otherwise = Nothing where - TimedMessagesPreference {ttl} = preference (userPreference :: ContactUserPref TimedMessagesPreference) + TimedMessagesPreference {ttl} = case userPreference of + CUPContact {preference} -> preference + CUPUser {preference} -> preference groupTimedTTL :: GroupInfo -> Maybe (Maybe Int) groupTimedTTL GroupInfo {fullGroupPreferences = FullGroupPreferences {timedMessages = TimedMessagesGroupPreference {enable, ttl}}} @@ -388,6 +421,12 @@ deriving instance Show ACIReaction data JSONCIReaction c d = JSONCIReaction {chatInfo :: ChatInfo c, chatReaction :: CIReaction c d} +type family ChatTypeQuotable (a :: ChatType) :: Constraint where + ChatTypeQuotable CTDirect = () + ChatTypeQuotable CTGroup = () + ChatTypeQuotable a = + (Int ~ Bool, TypeError (Type.Text "ChatType " :<>: ShowType a :<>: Type.Text " cannot be quoted")) + data CIQDirection (c :: ChatType) where CIQDirectSnd :: CIQDirection 'CTDirect CIQDirectRcv :: CIQDirection 'CTDirect @@ -396,7 +435,7 @@ data CIQDirection (c :: ChatType) where deriving instance Show (CIQDirection c) -data ACIQDirection = forall c. ChatTypeI c => ACIQDirection (SChatType c) (CIQDirection c) +data ACIQDirection = forall c. (ChatTypeI c, ChatTypeQuotable c) => ACIQDirection (SChatType c) (CIQDirection c) jsonCIQDirection :: CIQDirection c -> Maybe JSONCIDirection jsonCIQDirection = \case @@ -406,13 +445,15 @@ jsonCIQDirection = \case CIQGroupRcv (Just m) -> Just $ JCIGroupRcv m CIQGroupRcv Nothing -> Nothing -jsonACIQDirection :: Maybe JSONCIDirection -> ACIQDirection +jsonACIQDirection :: Maybe JSONCIDirection -> Either String ACIQDirection jsonACIQDirection = \case - Just JCIDirectSnd -> ACIQDirection SCTDirect CIQDirectSnd - Just JCIDirectRcv -> ACIQDirection SCTDirect CIQDirectRcv - Just JCIGroupSnd -> ACIQDirection SCTGroup CIQGroupSnd - Just (JCIGroupRcv m) -> ACIQDirection SCTGroup $ CIQGroupRcv (Just m) - Nothing -> ACIQDirection SCTGroup $ CIQGroupRcv Nothing + Just JCIDirectSnd -> Right $ ACIQDirection SCTDirect CIQDirectSnd + Just JCIDirectRcv -> Right $ ACIQDirection SCTDirect CIQDirectRcv + Just JCIGroupSnd -> Right $ ACIQDirection SCTGroup CIQGroupSnd + Just (JCIGroupRcv m) -> Right $ ACIQDirection SCTGroup $ CIQGroupRcv (Just m) + Nothing -> Right $ ACIQDirection SCTGroup $ CIQGroupRcv Nothing + Just JCILocalSnd -> Left "unquotable" + Just JCILocalRcv -> Left "unquotable" quoteMsgDirection :: CIQDirection c -> MsgDirection quoteMsgDirection = \case @@ -431,7 +472,7 @@ data CIFile (d :: MsgDirection) = CIFile } deriving (Show) -data FileProtocol = FPSMP | FPXFTP +data FileProtocol = FPSMP | FPXFTP | FPLocal deriving (Eq, Show, Ord) instance FromField FileProtocol where fromField = fromTextField_ textDecode @@ -449,10 +490,12 @@ instance TextEncoding FileProtocol where textDecode = \case "smp" -> Just FPSMP "xftp" -> Just FPXFTP + "local" -> Just FPLocal _ -> Nothing textEncode = \case FPSMP -> "smp" FPXFTP -> "xftp" + FPLocal -> "local" data CIFileStatus (d :: MsgDirection) where CIFSSndStored :: CIFileStatus 'MDSnd @@ -718,6 +761,7 @@ type ChatItemTs = UTCTime data SChatType (c :: ChatType) where SCTDirect :: SChatType 'CTDirect SCTGroup :: SChatType 'CTGroup + SCTLocal :: SChatType 'CTLocal SCTContactRequest :: SChatType 'CTContactRequest SCTContactConnection :: SChatType 'CTContactConnection @@ -726,6 +770,7 @@ deriving instance Show (SChatType c) instance TestEquality SChatType where testEquality SCTDirect SCTDirect = Just Refl testEquality SCTGroup SCTGroup = Just Refl + testEquality SCTLocal SCTLocal = Just Refl testEquality SCTContactRequest SCTContactRequest = Just Refl testEquality SCTContactConnection SCTContactConnection = Just Refl testEquality _ _ = Nothing @@ -739,6 +784,8 @@ instance ChatTypeI 'CTDirect where chatTypeI = SCTDirect instance ChatTypeI 'CTGroup where chatTypeI = SCTGroup +instance ChatTypeI 'CTLocal where chatTypeI = SCTLocal + instance ChatTypeI 'CTContactRequest where chatTypeI = SCTContactRequest instance ChatTypeI 'CTContactConnection where chatTypeI = SCTContactConnection @@ -747,6 +794,7 @@ toChatType :: SChatType c -> ChatType toChatType = \case SCTDirect -> CTDirect SCTGroup -> CTGroup + SCTLocal -> CTLocal SCTContactRequest -> CTContactRequest SCTContactConnection -> CTContactConnection @@ -754,6 +802,7 @@ aChatType :: ChatType -> AChatType aChatType = \case CTDirect -> ACT SCTDirect CTGroup -> ACT SCTGroup + CTLocal -> ACT SCTLocal CTContactRequest -> ACT SCTContactRequest CTContactConnection -> ACT SCTContactConnection @@ -880,6 +929,7 @@ msgDeliveryStatusT' s = data CIDeleted (c :: ChatType) where CIDeleted :: Maybe UTCTime -> CIDeleted c CIBlocked :: Maybe UTCTime -> CIDeleted 'CTGroup + CIBlockedByAdmin :: Maybe UTCTime -> CIDeleted 'CTGroup CIModerated :: Maybe UTCTime -> GroupMember -> CIDeleted 'CTGroup deriving instance Show (CIDeleted c) @@ -889,6 +939,7 @@ data ACIDeleted = forall c. ChatTypeI c => ACIDeleted (SChatType c) (CIDeleted c data JSONCIDeleted = JCIDDeleted {deletedTs :: Maybe UTCTime, chatType :: ChatType} | JCIDBlocked {deletedTs :: Maybe UTCTime} + | JCIDBlockedByAdmin {deletedTs :: Maybe UTCTime} | JCIDModerated {deletedTs :: Maybe UTCTime, byGroupMember :: GroupMember} deriving (Show) @@ -896,18 +947,21 @@ jsonCIDeleted :: forall d. ChatTypeI d => CIDeleted d -> JSONCIDeleted jsonCIDeleted = \case CIDeleted ts -> JCIDDeleted ts (toChatType $ chatTypeI @d) CIBlocked ts -> JCIDBlocked ts + CIBlockedByAdmin ts -> JCIDBlockedByAdmin ts CIModerated ts m -> JCIDModerated ts m jsonACIDeleted :: JSONCIDeleted -> ACIDeleted jsonACIDeleted = \case JCIDDeleted ts cType -> case aChatType cType of ACT c -> ACIDeleted c $ CIDeleted ts JCIDBlocked ts -> ACIDeleted SCTGroup $ CIBlocked ts + JCIDBlockedByAdmin ts -> ACIDeleted SCTGroup $ CIBlockedByAdmin ts JCIDModerated ts m -> ACIDeleted SCTGroup (CIModerated ts m) itemDeletedTs :: CIDeleted d -> Maybe UTCTime itemDeletedTs = \case CIDeleted ts -> ts CIBlocked ts -> ts + CIBlockedByAdmin ts -> ts CIModerated ts _ -> ts data ChatItemInfo = ChatItemInfo @@ -1040,7 +1094,7 @@ instance FromJSON ACIDirection where parseJSON v = jsonACIDirection <$> J.parseJSON v instance ChatTypeI c => FromJSON (CIQDirection c) where - parseJSON v = (\(ACIQDirection _ x) -> checkChatType x) . jsonACIQDirection <$?> J.parseJSON v + parseJSON v = (jsonACIQDirection >=> \(ACIQDirection _ x) -> checkChatType x) <$?> J.parseJSON v instance ToJSON (CIQDirection c) where toJSON = J.toJSON . jsonCIQDirection diff --git a/src/Simplex/Chat/Messages/Batch.hs b/src/Simplex/Chat/Messages/Batch.hs index 4c1b59f25a..690ae5828f 100644 --- a/src/Simplex/Chat/Messages/Batch.hs +++ b/src/Simplex/Chat/Messages/Batch.hs @@ -4,10 +4,11 @@ {-# LANGUAGE OverloadedStrings #-} {-# LANGUAGE ScopedTypeVariables #-} -module Simplex.Chat.Messages.Batch ( - MsgBatch (..), - batchMessages, -) where +module Simplex.Chat.Messages.Batch + ( MsgBatch (..), + batchMessages, + ) +where import Data.ByteString.Char8 (ByteString) import qualified Data.ByteString.Char8 as B diff --git a/src/Simplex/Chat/Messages/CIContent.hs b/src/Simplex/Chat/Messages/CIContent.hs index b878949cab..f0ce2d6274 100644 --- a/src/Simplex/Chat/Messages/CIContent.hs +++ b/src/Simplex/Chat/Messages/CIContent.hs @@ -138,6 +138,7 @@ data CIContent (d :: MsgDirection) where CIRcvGroupFeatureRejected :: GroupFeature -> CIContent 'MDRcv CISndModerated :: CIContent 'MDSnd CIRcvModerated :: CIContent 'MDRcv + CIRcvBlocked :: CIContent 'MDRcv CIInvalidJSON :: Text -> CIContent d -- ^ This type is used both in API and in DB, so we use different JSON encodings for the database and for the API -- ! ^ Nested sum types also have to use different encodings for database and API @@ -169,12 +170,15 @@ ciRequiresAttention content = case msgDirection @d of CIRcvIntegrityError _ -> True CIRcvDecryptionError {} -> True CIRcvGroupInvitation {} -> True - CIRcvDirectEvent _ -> False + CIRcvDirectEvent rde -> case rde of + RDEContactDeleted -> False + RDEProfileUpdated {} -> True CIRcvGroupEvent rge -> case rge of RGEMemberAdded {} -> False RGEMemberConnected -> False RGEMemberLeft -> False RGEMemberRole {} -> False + RGEMemberBlocked {} -> False RGEUserRole _ -> True RGEMemberDeleted {} -> False RGEUserDeleted -> True @@ -182,6 +186,7 @@ ciRequiresAttention content = case msgDirection @d of RGEGroupUpdated _ -> False RGEInvitedViaGroupLink -> False RGEMemberCreatedContact -> False + RGEMemberProfileUpdated {} -> False CIRcvConnEvent _ -> True CIRcvChatFeature {} -> False CIRcvChatPreference {} -> False @@ -189,6 +194,7 @@ ciRequiresAttention content = case msgDirection @d of CIRcvChatFeatureRejected _ -> True CIRcvGroupFeatureRejected _ -> True CIRcvModerated -> True + CIRcvBlocked -> False CIInvalidJSON _ -> False newtype DBMsgErrorType = DBME MsgErrorType @@ -243,6 +249,7 @@ ciContentToText = \case CIRcvGroupFeatureRejected feature -> groupFeatureNameText feature <> ": received, prohibited" CISndModerated -> ciModeratedText CIRcvModerated -> ciModeratedText + CIRcvBlocked -> "blocked" CIInvalidJSON _ -> "invalid content JSON" ciGroupInvitationToText :: CIGroupInvitation -> GroupMemberRole -> Text @@ -252,6 +259,7 @@ ciGroupInvitationToText CIGroupInvitation {groupProfile = GroupProfile {displayN rcvDirectEventToText :: RcvDirectEvent -> Text rcvDirectEventToText = \case RDEContactDeleted -> "contact deleted" + RDEProfileUpdated {} -> "updated profile" rcvGroupEventToText :: RcvGroupEvent -> Text rcvGroupEventToText = \case @@ -259,6 +267,7 @@ rcvGroupEventToText = \case RGEMemberConnected -> "connected" RGEMemberLeft -> "left" RGEMemberRole _ p r -> "changed role of " <> profileToText p <> " to " <> safeDecodeUtf8 (strEncode r) + RGEMemberBlocked _ p blocked -> (if blocked then "blocked" else "unblocked") <> " " <> profileToText p RGEUserRole r -> "changed your role to " <> safeDecodeUtf8 (strEncode r) RGEMemberDeleted _ p -> "removed " <> profileToText p RGEUserDeleted -> "removed you" @@ -266,10 +275,12 @@ rcvGroupEventToText = \case RGEGroupUpdated _ -> "group profile updated" RGEInvitedViaGroupLink -> "invited via your group link" RGEMemberCreatedContact -> "started direct connection with you" + RGEMemberProfileUpdated {} -> "updated profile" sndGroupEventToText :: SndGroupEvent -> Text sndGroupEventToText = \case SGEMemberRole _ p r -> "changed role of " <> profileToText p <> " to " <> safeDecodeUtf8 (strEncode r) + SGEMemberBlocked _ p blocked -> (if blocked then "blocked" else "unblocked") <> " " <> profileToText p SGEUserRole r -> "changed role for yourself to " <> safeDecodeUtf8 (strEncode r) SGEMemberDeleted _ p -> "removed " <> profileToText p SGEUserLeft -> "left" @@ -370,6 +381,7 @@ data JSONCIContent | JCIRcvGroupFeatureRejected {groupFeature :: GroupFeature} | JCISndModerated | JCIRcvModerated + | JCIRcvBlocked | JCIInvalidJSON {direction :: MsgDirection, json :: Text} jsonCIContent :: forall d. MsgDirectionI d => CIContent d -> JSONCIContent @@ -399,6 +411,7 @@ jsonCIContent = \case CIRcvGroupFeatureRejected groupFeature -> JCIRcvGroupFeatureRejected {groupFeature} CISndModerated -> JCISndModerated CIRcvModerated -> JCIRcvModerated + CIRcvBlocked -> JCIRcvBlocked CIInvalidJSON json -> JCIInvalidJSON (toMsgDirection $ msgDirection @d) json aciContentJSON :: JSONCIContent -> ACIContent @@ -428,6 +441,7 @@ aciContentJSON = \case JCIRcvGroupFeatureRejected {groupFeature} -> ACIContent SMDRcv $ CIRcvGroupFeatureRejected groupFeature JCISndModerated -> ACIContent SMDSnd CISndModerated JCIRcvModerated -> ACIContent SMDRcv CIRcvModerated + JCIRcvBlocked -> ACIContent SMDRcv CIRcvBlocked JCIInvalidJSON dir json -> case fromMsgDirection dir of AMsgDirection d -> ACIContent d $ CIInvalidJSON json @@ -458,6 +472,7 @@ data DBJSONCIContent | DBJCIRcvGroupFeatureRejected {groupFeature :: GroupFeature} | DBJCISndModerated | DBJCIRcvModerated + | DBJCIRcvBlocked | DBJCIInvalidJSON {direction :: MsgDirection, json :: Text} dbJsonCIContent :: forall d. MsgDirectionI d => CIContent d -> DBJSONCIContent @@ -487,6 +502,7 @@ dbJsonCIContent = \case CIRcvGroupFeatureRejected groupFeature -> DBJCIRcvGroupFeatureRejected {groupFeature} CISndModerated -> DBJCISndModerated CIRcvModerated -> DBJCIRcvModerated + CIRcvBlocked -> DBJCIRcvBlocked CIInvalidJSON json -> DBJCIInvalidJSON (toMsgDirection $ msgDirection @d) json aciContentDBJSON :: DBJSONCIContent -> ACIContent @@ -516,6 +532,7 @@ aciContentDBJSON = \case DBJCIRcvGroupFeatureRejected {groupFeature} -> ACIContent SMDRcv $ CIRcvGroupFeatureRejected groupFeature DBJCISndModerated -> ACIContent SMDSnd CISndModerated DBJCIRcvModerated -> ACIContent SMDRcv CIRcvModerated + DBJCIRcvBlocked -> ACIContent SMDRcv CIRcvBlocked DBJCIInvalidJSON dir json -> case fromMsgDirection dir of AMsgDirection d -> ACIContent d $ CIInvalidJSON json @@ -608,4 +625,5 @@ toCIContentTag ciContent = case ciContent of CIRcvGroupFeatureRejected _ -> "rcvGroupFeatureRejected" CISndModerated -> "sndModerated" CIRcvModerated -> "rcvModerated" + CIRcvBlocked -> "rcvBlocked" CIInvalidJSON _ -> "invalidJSON" diff --git a/src/Simplex/Chat/Messages/CIContent/Events.hs b/src/Simplex/Chat/Messages/CIContent/Events.hs index 16851859e3..05417a2e14 100644 --- a/src/Simplex/Chat/Messages/CIContent/Events.hs +++ b/src/Simplex/Chat/Messages/CIContent/Events.hs @@ -15,6 +15,7 @@ data RcvGroupEvent | RGEMemberConnected -- CRUserJoinedGroup, CRJoinedGroupMember, CRConnectedToGroupMember | RGEMemberLeft -- CRLeftMember | RGEMemberRole {groupMemberId :: GroupMemberId, profile :: Profile, role :: GroupMemberRole} + | RGEMemberBlocked {groupMemberId :: GroupMemberId, profile :: Profile, blocked :: Bool} -- CRMemberBlockedForAll | RGEUserRole {role :: GroupMemberRole} | RGEMemberDeleted {groupMemberId :: GroupMemberId, profile :: Profile} -- CRDeletedMember | RGEUserDeleted -- CRDeletedMemberUser @@ -25,10 +26,12 @@ data RcvGroupEvent -- and be created as unread without adding / working around new status for sent items | RGEInvitedViaGroupLink -- CRSentGroupInvitationViaLink | RGEMemberCreatedContact -- CRNewMemberContactReceivedInv + | RGEMemberProfileUpdated {fromProfile :: Profile, toProfile :: Profile} -- CRGroupMemberUpdated deriving (Show) data SndGroupEvent = SGEMemberRole {groupMemberId :: GroupMemberId, profile :: Profile, role :: GroupMemberRole} + | SGEMemberBlocked {groupMemberId :: GroupMemberId, profile :: Profile, blocked :: Bool} -- CRMemberBlockedForAllUser | SGEUserRole {role :: GroupMemberRole} | SGEMemberDeleted {groupMemberId :: GroupMemberId, profile :: Profile} -- CRUserDeletedMember | SGEUserLeft -- CRLeftMemberUser @@ -47,8 +50,8 @@ data SndConnEvent deriving (Show) data RcvDirectEvent - = -- RDEProfileChanged {...} - RDEContactDeleted + = RDEContactDeleted + | RDEProfileUpdated {fromProfile :: Profile, toProfile :: Profile} -- CRContactUpdated deriving (Show) -- platform-specific JSON encoding (used in API) diff --git a/src/Simplex/Chat/Migrations/M20240102_note_folders.hs b/src/Simplex/Chat/Migrations/M20240102_note_folders.hs new file mode 100644 index 0000000000..02ad741662 --- /dev/null +++ b/src/Simplex/Chat/Migrations/M20240102_note_folders.hs @@ -0,0 +1,42 @@ +{-# LANGUAGE QuasiQuotes #-} + +module Simplex.Chat.Migrations.M20240102_note_folders where + +import Database.SQLite.Simple (Query) +import Database.SQLite.Simple.QQ (sql) + +m20240102_note_folders :: Query +m20240102_note_folders = + [sql| +CREATE TABLE note_folders ( + note_folder_id INTEGER PRIMARY KEY AUTOINCREMENT, + user_id INTEGER NOT NULL REFERENCES users ON DELETE CASCADE, + created_at TEXT NOT NULL DEFAULT(datetime('now')), + updated_at TEXT NOT NULL DEFAULT(datetime('now')), + chat_ts TEXT NOT NULL DEFAULT(datetime('now')), + favorite INTEGER NOT NULL DEFAULT 0, + unread_chat INTEGER NOT NULL DEFAULT 0 +); + +ALTER TABLE chat_items ADD COLUMN note_folder_id INTEGER DEFAULT NULL REFERENCES note_folders ON DELETE CASCADE; +ALTER TABLE files ADD COLUMN note_folder_id INTEGER DEFAULT NULL REFERENCES note_folders ON DELETE CASCADE; + +CREATE INDEX chat_items_note_folder_id ON chat_items(note_folder_id); +CREATE INDEX files_note_folder_id ON files(note_folder_id); +CREATE INDEX note_folders_user_id ON note_folders(user_id); + +INSERT INTO note_folders (user_id) SELECT user_id FROM users; +|] + +down_m20240102_note_folders :: Query +down_m20240102_note_folders = + [sql| +DROP INDEX chat_items_note_folder_id; +DROP INDEX files_note_folder_id; +DROP INDEX note_folders_user_id; + +ALTER TABLE chat_items DROP COLUMN note_folder_id; +ALTER TABLE files DROP COLUMN note_folder_id; + +DROP TABLE note_folders; +|] diff --git a/src/Simplex/Chat/Migrations/M20240104_members_profile_update.hs b/src/Simplex/Chat/Migrations/M20240104_members_profile_update.hs new file mode 100644 index 0000000000..5591c4bdcd --- /dev/null +++ b/src/Simplex/Chat/Migrations/M20240104_members_profile_update.hs @@ -0,0 +1,20 @@ +{-# LANGUAGE QuasiQuotes #-} + +module Simplex.Chat.Migrations.M20240104_members_profile_update where + +import Database.SQLite.Simple (Query) +import Database.SQLite.Simple.QQ (sql) + +m20240104_members_profile_update :: Query +m20240104_members_profile_update = + [sql| +ALTER TABLE users ADD COLUMN user_member_profile_updated_at TEXT; +ALTER TABLE groups ADD COLUMN user_member_profile_sent_at TEXT; +|] + +down_m20240104_members_profile_update :: Query +down_m20240104_members_profile_update = + [sql| +ALTER TABLE groups DROP COLUMN user_member_profile_sent_at; +ALTER TABLE users DROP COLUMN user_member_profile_updated_at; +|] diff --git a/src/Simplex/Chat/Migrations/M20240115_block_member_for_all.hs b/src/Simplex/Chat/Migrations/M20240115_block_member_for_all.hs new file mode 100644 index 0000000000..af2448e42c --- /dev/null +++ b/src/Simplex/Chat/Migrations/M20240115_block_member_for_all.hs @@ -0,0 +1,18 @@ +{-# LANGUAGE QuasiQuotes #-} + +module Simplex.Chat.Migrations.M20240115_block_member_for_all where + +import Database.SQLite.Simple (Query) +import Database.SQLite.Simple.QQ (sql) + +m20240115_block_member_for_all :: Query +m20240115_block_member_for_all = + [sql| +ALTER TABLE group_members ADD COLUMN member_restriction TEXT; +|] + +down_m20240115_block_member_for_all :: Query +down_m20240115_block_member_for_all = + [sql| +ALTER TABLE group_members DROP COLUMN member_restriction; +|] diff --git a/src/Simplex/Chat/Migrations/M20240122_indexes.hs b/src/Simplex/Chat/Migrations/M20240122_indexes.hs new file mode 100644 index 0000000000..7b708f8bbe --- /dev/null +++ b/src/Simplex/Chat/Migrations/M20240122_indexes.hs @@ -0,0 +1,26 @@ +{-# LANGUAGE QuasiQuotes #-} + +module Simplex.Chat.Migrations.M20240122_indexes where + +import Database.SQLite.Simple (Query) +import Database.SQLite.Simple.QQ (sql) + +m20240122_indexes :: Query +m20240122_indexes = + [sql| +CREATE INDEX idx_chat_items_contacts_created_at on chat_items (user_id, contact_id, created_at); +CREATE INDEX idx_chat_items_contacts_item_status on chat_items (user_id, contact_id, item_status); +CREATE INDEX idx_chat_items_groups_item_status on chat_items (user_id, group_id, item_status); +CREATE INDEX idx_chat_items_notes_created_at on chat_items (user_id, note_folder_id, created_at); +CREATE INDEX idx_chat_items_notes_item_status on chat_items (user_id, note_folder_id, item_status); +|] + +down_m20240122_indexes :: Query +down_m20240122_indexes = + [sql| +DROP INDEX idx_chat_items_contacts_created_at; +DROP INDEX idx_chat_items_contacts_item_status; +DROP INDEX idx_chat_items_groups_item_status; +DROP INDEX idx_chat_items_notes_created_at; +DROP INDEX idx_chat_items_notes_item_status; +|] diff --git a/src/Simplex/Chat/Migrations/chat_schema.sql b/src/Simplex/Chat/Migrations/chat_schema.sql index 7a3be6e3ae..efed6d168a 100644 --- a/src/Simplex/Chat/Migrations/chat_schema.sql +++ b/src/Simplex/Chat/Migrations/chat_schema.sql @@ -33,7 +33,8 @@ CREATE TABLE users( view_pwd_salt BLOB, show_ntfs INTEGER NOT NULL DEFAULT 1, send_rcpts_contacts INTEGER NOT NULL DEFAULT 0, - send_rcpts_small_groups INTEGER NOT NULL DEFAULT 0, -- 1 for active user + send_rcpts_small_groups INTEGER NOT NULL DEFAULT 0, + user_member_profile_updated_at TEXT, -- 1 for active user FOREIGN KEY(user_id, local_display_name) REFERENCES display_names(user_id, local_display_name) ON DELETE CASCADE @@ -118,7 +119,8 @@ CREATE TABLE groups( chat_ts TEXT, favorite INTEGER NOT NULL DEFAULT 0, send_rcpts INTEGER, - via_group_link_uri_hash BLOB, -- received + via_group_link_uri_hash BLOB, + user_member_profile_sent_at TEXT, -- received FOREIGN KEY(user_id, local_display_name) REFERENCES display_names(user_id, local_display_name) ON DELETE CASCADE @@ -150,6 +152,7 @@ CREATE TABLE group_members( invited_by_group_member_id INTEGER REFERENCES group_members ON DELETE SET NULL, peer_chat_min_version INTEGER NOT NULL DEFAULT 1, peer_chat_max_version INTEGER NOT NULL DEFAULT 1, + member_restriction TEXT, FOREIGN KEY(user_id, local_display_name) REFERENCES display_names(user_id, local_display_name) ON DELETE CASCADE @@ -189,7 +192,8 @@ CREATE TABLE files( agent_snd_file_deleted INTEGER DEFAULT 0 CHECK(agent_snd_file_deleted NOT NULL), protocol TEXT NOT NULL DEFAULT 'smp', file_crypto_key BLOB, - file_crypto_nonce BLOB + file_crypto_nonce BLOB, + note_folder_id INTEGER DEFAULT NULL REFERENCES note_folders ON DELETE CASCADE ); CREATE TABLE snd_files( file_id INTEGER NOT NULL REFERENCES files ON DELETE CASCADE, @@ -368,7 +372,8 @@ CREATE TABLE chat_items( item_deleted_by_group_member_id INTEGER REFERENCES group_members ON DELETE SET NULL, item_deleted_ts TEXT, forwarded_by_group_member_id INTEGER REFERENCES group_members ON DELETE SET NULL, - item_content_tag TEXT + item_content_tag TEXT, + note_folder_id INTEGER DEFAULT NULL REFERENCES note_folders ON DELETE CASCADE ); CREATE TABLE chat_item_messages( chat_item_id INTEGER NOT NULL REFERENCES chat_items ON DELETE CASCADE, @@ -547,6 +552,15 @@ CREATE TABLE IF NOT EXISTS "msg_deliveries"( agent_ack_cmd_id INTEGER, -- broker_ts for received, created_at for sent delivery_status TEXT -- MsgDeliveryStatus ); +CREATE TABLE note_folders( + note_folder_id INTEGER PRIMARY KEY AUTOINCREMENT, + user_id INTEGER NOT NULL REFERENCES users ON DELETE CASCADE, + created_at TEXT NOT NULL DEFAULT(datetime('now')), + updated_at TEXT NOT NULL DEFAULT(datetime('now')), + chat_ts TEXT NOT NULL DEFAULT(datetime('now')), + favorite INTEGER NOT NULL DEFAULT 0, + unread_chat INTEGER NOT NULL DEFAULT 0 +); CREATE INDEX contact_profiles_index ON contact_profiles( display_name, full_name @@ -812,3 +826,31 @@ CREATE INDEX idx_msg_deliveries_agent_msg_id ON "msg_deliveries"( connection_id, agent_msg_id ); +CREATE INDEX chat_items_note_folder_id ON chat_items(note_folder_id); +CREATE INDEX files_note_folder_id ON files(note_folder_id); +CREATE INDEX note_folders_user_id ON note_folders(user_id); +CREATE INDEX idx_chat_items_contacts_created_at on chat_items( + user_id, + contact_id, + created_at +); +CREATE INDEX idx_chat_items_contacts_item_status on chat_items( + user_id, + contact_id, + item_status +); +CREATE INDEX idx_chat_items_groups_item_status on chat_items( + user_id, + group_id, + item_status +); +CREATE INDEX idx_chat_items_notes_created_at on chat_items( + user_id, + note_folder_id, + created_at +); +CREATE INDEX idx_chat_items_notes_item_status on chat_items( + user_id, + note_folder_id, + item_status +); diff --git a/src/Simplex/Chat/Mobile.hs b/src/Simplex/Chat/Mobile.hs index 3671844d7f..7c74a7325a 100644 --- a/src/Simplex/Chat/Mobile.hs +++ b/src/Simplex/Chat/Mobile.hs @@ -197,6 +197,7 @@ mobileChatOpts dbFilePrefix = deviceName = Nothing, chatCmd = "", chatCmdDelay = 3, + chatCmdLog = CCLNone, chatServerPort = Nothing, optFilesFolder = Nothing, showReactions = False, diff --git a/src/Simplex/Chat/Mobile/Shared.hs b/src/Simplex/Chat/Mobile/Shared.hs index d55ccc7969..fcde581ea3 100644 --- a/src/Simplex/Chat/Mobile/Shared.hs +++ b/src/Simplex/Chat/Mobile/Shared.hs @@ -3,7 +3,7 @@ module Simplex.Chat.Mobile.Shared where import qualified Data.ByteString as B -import Data.ByteString.Internal (ByteString (..), memcpy) +import Data.ByteString.Internal (ByteString (..)) import qualified Data.ByteString.Lazy as LB import qualified Data.ByteString.Lazy.Internal as LB import Foreign @@ -16,12 +16,12 @@ type JSONByteString = LB.ByteString getByteString :: Ptr Word8 -> CInt -> IO ByteString getByteString ptr len = do fp <- newForeignPtr_ ptr - pure $ PS fp 0 $ fromIntegral len + pure $ PS fp 0 (fromIntegral len) {-# INLINE getByteString #-} putByteString :: Ptr Word8 -> ByteString -> IO () putByteString ptr (PS fp offset len) = - withForeignPtr fp $ \p -> memcpy ptr (p `plusPtr` offset) len + withForeignPtr fp $ \p -> copyBytes ptr (p `plusPtr` offset) len {-# INLINE putByteString #-} putLazyByteString :: Ptr Word8 -> LB.ByteString -> IO () diff --git a/src/Simplex/Chat/Options.hs b/src/Simplex/Chat/Options.hs index 85298ae310..a222e2e77b 100644 --- a/src/Simplex/Chat/Options.hs +++ b/src/Simplex/Chat/Options.hs @@ -8,6 +8,7 @@ module Simplex.Chat.Options ( ChatOpts (..), CoreChatOpts (..), + ChatCmdLog (..), chatOptsP, coreChatOptsP, getChatOpts, @@ -37,6 +38,7 @@ data ChatOpts = ChatOpts deviceName :: Maybe Text, chatCmd :: String, chatCmdDelay :: Int, + chatCmdLog :: ChatCmdLog, chatServerPort :: Maybe String, optFilesFolder :: Maybe FilePath, showReactions :: Bool, @@ -62,6 +64,9 @@ data CoreChatOpts = CoreChatOpts highlyAvailable :: Bool } +data ChatCmdLog = CCLAll | CCLMessages | CCLNone + deriving (Eq) + agentLogLevel :: ChatLogLevel -> LogLevel agentLogLevel = \case CLLDebug -> LogDebug @@ -229,6 +234,14 @@ chatOptsP appDir defaultDbFileName = do <> value 3 <> showDefault ) + chatCmdLog <- + option + parseChatCmdLog + ( long "execute-log" + <> metavar "EXEC_LOG" + <> help "Log during command execution: all, messages, none (default)" + <> value CCLNone + ) chatServerPort <- option parseServerPort @@ -288,6 +301,7 @@ chatOptsP appDir defaultDbFileName = do deviceName, chatCmd, chatCmdDelay, + chatCmdLog, chatServerPort, optFilesFolder, showReactions, @@ -327,6 +341,13 @@ parseLogLevel = eitherReader $ \case "important" -> Right CLLImportant _ -> Left "Invalid log level" +parseChatCmdLog :: ReadM ChatCmdLog +parseChatCmdLog = eitherReader $ \case + "all" -> Right CCLAll + "messages" -> Right CCLMessages + "none" -> Right CCLNone + _ -> Left "Invalid chat command log level" + getChatOpts :: FilePath -> FilePath -> IO ChatOpts getChatOpts appDir defaultDbFileName = execParser $ diff --git a/src/Simplex/Chat/Protocol.hs b/src/Simplex/Chat/Protocol.hs index 2aa360b4b1..c4423bfe6a 100644 --- a/src/Simplex/Chat/Protocol.hs +++ b/src/Simplex/Chat/Protocol.hs @@ -54,7 +54,7 @@ import Simplex.Messaging.Version hiding (version) -- This indirection is needed for backward/forward compatibility testing. -- Testing with real app versions is still needed, as tests use the current code with different version ranges, not the old code. currentChatVersion :: Version -currentChatVersion = 5 +currentChatVersion = 7 -- This should not be used directly in code, instead use `chatVRange` from ChatConfig (see comment above) supportedChatVRange :: VersionRange @@ -80,6 +80,14 @@ groupForwardVRange = mkVersionRange 4 currentChatVersion batchSendVRange :: VersionRange batchSendVRange = mkVersionRange 5 currentChatVersion +-- version range that supports sending group welcome message in group history +groupHistoryIncludeWelcomeVRange :: VersionRange +groupHistoryIncludeWelcomeVRange = mkVersionRange 6 currentChatVersion + +-- version range that supports sending member profile updates to groups +memberProfileUpdateVRange :: VersionRange +memberProfileUpdateVRange = mkVersionRange 7 currentChatVersion + data ConnectionEntity = RcvDirectMsgConnection {entityConnection :: Connection, contact :: Maybe Contact} | RcvGroupMsgConnection {entityConnection :: Connection, groupInfo :: GroupInfo, groupMember :: GroupMember} @@ -236,11 +244,12 @@ data ChatMsgEvent (e :: MsgEncoding) where XGrpLinkInv :: GroupLinkInvitation -> ChatMsgEvent 'Json XGrpLinkMem :: Profile -> ChatMsgEvent 'Json XGrpMemNew :: MemberInfo -> ChatMsgEvent 'Json - XGrpMemIntro :: MemberInfo -> ChatMsgEvent 'Json + XGrpMemIntro :: MemberInfo -> Maybe MemberRestrictions -> ChatMsgEvent 'Json XGrpMemInv :: MemberId -> IntroInvitation -> ChatMsgEvent 'Json XGrpMemFwd :: MemberInfo -> IntroInvitation -> ChatMsgEvent 'Json XGrpMemInfo :: MemberId -> Profile -> ChatMsgEvent 'Json XGrpMemRole :: MemberId -> GroupMemberRole -> ChatMsgEvent 'Json + XGrpMemRestrict :: MemberId -> MemberRestrictions -> ChatMsgEvent 'Json XGrpMemCon :: MemberId -> ChatMsgEvent 'Json XGrpMemConAll :: MemberId -> ChatMsgEvent 'Json -- TODO not implemented XGrpMemDel :: MemberId -> ChatMsgEvent 'Json @@ -282,6 +291,7 @@ isForwardedGroupMsg ev = case ev of XInfo _ -> True XGrpMemNew _ -> True XGrpMemRole {} -> True + XGrpMemRestrict {} -> True XGrpMemDel _ -> True -- TODO there should be a special logic when deleting host member (e.g., host forwards it before deleting connections) XGrpLeave -> True XGrpDel -> True -- TODO there should be a special logic - host should forward before deleting connections @@ -293,6 +303,14 @@ forwardedGroupMsg msg@ChatMessage {chatMsgEvent} = case encoding @e of SJson | isForwardedGroupMsg chatMsgEvent -> Just msg _ -> Nothing +-- applied after checking forwardedGroupMsg and building list of group members to forward to, see Chat +forwardedToGroupMembers :: forall e. MsgEncodingI e => [GroupMember] -> ChatMessage e -> [GroupMember] +forwardedToGroupMembers ms ChatMessage {chatMsgEvent} = case encoding @e of + SJson -> case chatMsgEvent of + XGrpMemRestrict mId _ -> filter (\GroupMember {memberId} -> memberId /= mId) ms + _ -> ms + _ -> [] + data MsgReaction = MREmoji {emoji :: MREmojiChar} | MRUnknown {tag :: Text, json :: J.Object} deriving (Eq, Show) @@ -621,6 +639,7 @@ data CMEventTag (e :: MsgEncoding) where XGrpMemFwd_ :: CMEventTag 'Json XGrpMemInfo_ :: CMEventTag 'Json XGrpMemRole_ :: CMEventTag 'Json + XGrpMemRestrict_ :: CMEventTag 'Json XGrpMemCon_ :: CMEventTag 'Json XGrpMemConAll_ :: CMEventTag 'Json XGrpMemDel_ :: CMEventTag 'Json @@ -670,6 +689,7 @@ instance MsgEncodingI e => StrEncoding (CMEventTag e) where XGrpMemFwd_ -> "x.grp.mem.fwd" XGrpMemInfo_ -> "x.grp.mem.info" XGrpMemRole_ -> "x.grp.mem.role" + XGrpMemRestrict_ -> "x.grp.mem.restrict" XGrpMemCon_ -> "x.grp.mem.con" XGrpMemConAll_ -> "x.grp.mem.con.all" XGrpMemDel_ -> "x.grp.mem.del" @@ -720,6 +740,7 @@ instance StrEncoding ACMEventTag where "x.grp.mem.fwd" -> XGrpMemFwd_ "x.grp.mem.info" -> XGrpMemInfo_ "x.grp.mem.role" -> XGrpMemRole_ + "x.grp.mem.restrict" -> XGrpMemRestrict_ "x.grp.mem.con" -> XGrpMemCon_ "x.grp.mem.con.all" -> XGrpMemConAll_ "x.grp.mem.del" -> XGrpMemDel_ @@ -761,11 +782,12 @@ toCMEventTag msg = case msg of XGrpLinkInv _ -> XGrpLinkInv_ XGrpLinkMem _ -> XGrpLinkMem_ XGrpMemNew _ -> XGrpMemNew_ - XGrpMemIntro _ -> XGrpMemIntro_ + XGrpMemIntro _ _ -> XGrpMemIntro_ XGrpMemInv _ _ -> XGrpMemInv_ XGrpMemFwd _ _ -> XGrpMemFwd_ XGrpMemInfo _ _ -> XGrpMemInfo_ XGrpMemRole _ _ -> XGrpMemRole_ + XGrpMemRestrict _ _ -> XGrpMemRestrict_ XGrpMemCon _ -> XGrpMemCon_ XGrpMemConAll _ -> XGrpMemConAll_ XGrpMemDel _ -> XGrpMemDel_ @@ -860,11 +882,12 @@ appJsonToCM AppMessageJson {v, msgId, event, params} = do XGrpLinkInv_ -> XGrpLinkInv <$> p "groupLinkInvitation" XGrpLinkMem_ -> XGrpLinkMem <$> p "profile" XGrpMemNew_ -> XGrpMemNew <$> p "memberInfo" - XGrpMemIntro_ -> XGrpMemIntro <$> p "memberInfo" + XGrpMemIntro_ -> XGrpMemIntro <$> p "memberInfo" <*> opt "memberRestrictions" XGrpMemInv_ -> XGrpMemInv <$> p "memberId" <*> p "memberIntro" XGrpMemFwd_ -> XGrpMemFwd <$> p "memberInfo" <*> p "memberIntro" XGrpMemInfo_ -> XGrpMemInfo <$> p "memberId" <*> p "profile" XGrpMemRole_ -> XGrpMemRole <$> p "memberId" <*> p "role" + XGrpMemRestrict_ -> XGrpMemRestrict <$> p "memberId" <*> p "memberRestrictions" XGrpMemCon_ -> XGrpMemCon <$> p "memberId" XGrpMemConAll_ -> XGrpMemConAll <$> p "memberId" XGrpMemDel_ -> XGrpMemDel <$> p "memberId" @@ -920,11 +943,12 @@ chatToAppMessage ChatMessage {chatVRange, msgId, chatMsgEvent} = case encoding @ XGrpLinkInv groupLinkInv -> o ["groupLinkInvitation" .= groupLinkInv] XGrpLinkMem profile -> o ["profile" .= profile] XGrpMemNew memInfo -> o ["memberInfo" .= memInfo] - XGrpMemIntro memInfo -> o ["memberInfo" .= memInfo] + XGrpMemIntro memInfo memRestrictions -> o $ ("memberRestrictions" .=? memRestrictions) ["memberInfo" .= memInfo] XGrpMemInv memId memIntro -> o ["memberId" .= memId, "memberIntro" .= memIntro] XGrpMemFwd memInfo memIntro -> o ["memberInfo" .= memInfo, "memberIntro" .= memIntro] XGrpMemInfo memId profile -> o ["memberId" .= memId, "profile" .= profile] XGrpMemRole memId role -> o ["memberId" .= memId, "role" .= role] + XGrpMemRestrict memId memRestrictions -> o ["memberId" .= memId, "memberRestrictions" .= memRestrictions] XGrpMemCon memId -> o ["memberId" .= memId] XGrpMemConAll memId -> o ["memberId" .= memId] XGrpMemDel memId -> o ["memberId" .= memId] diff --git a/src/Simplex/Chat/Remote.hs b/src/Simplex/Chat/Remote.hs index ee41fba594..d5f66224b9 100644 --- a/src/Simplex/Chat/Remote.hs +++ b/src/Simplex/Chat/Remote.hs @@ -72,11 +72,11 @@ import UnliftIO.Directory (copyFile, createDirectoryIfMissing, doesDirectoryExis -- when acting as host minRemoteCtrlVersion :: AppVersion -minRemoteCtrlVersion = AppVersion [5, 4, 2, 0] +minRemoteCtrlVersion = AppVersion [5, 5, 0, 2] -- when acting as controller minRemoteHostVersion :: AppVersion -minRemoteHostVersion = AppVersion [5, 4, 2, 0] +minRemoteHostVersion = AppVersion [5, 5, 0, 2] currentAppVersion :: AppVersion currentAppVersion = AppVersion SC.version diff --git a/src/Simplex/Chat/Store/Connections.hs b/src/Simplex/Chat/Store/Connections.hs index 580120b2ae..fdc3703219 100644 --- a/src/Simplex/Chat/Store/Connections.hs +++ b/src/Simplex/Chat/Store/Connections.hs @@ -96,14 +96,16 @@ getConnectionEntity db vr user@User {userId, userContactId} agentConnId = do [sql| SELECT -- GroupInfo - g.group_id, g.local_display_name, gp.display_name, gp.full_name, gp.description, gp.image, g.host_conn_custom_user_profile_id, g.enable_ntfs, g.send_rcpts, g.favorite, gp.preferences, g.created_at, g.updated_at, g.chat_ts, + g.group_id, g.local_display_name, gp.display_name, gp.full_name, gp.description, gp.image, + g.host_conn_custom_user_profile_id, g.enable_ntfs, g.send_rcpts, g.favorite, gp.preferences, + g.created_at, g.updated_at, g.chat_ts, g.user_member_profile_sent_at, -- GroupInfo {membership} mu.group_member_id, mu.group_id, mu.member_id, mu.peer_chat_min_version, mu.peer_chat_max_version, mu.member_role, mu.member_category, - mu.member_status, mu.show_messages, mu.invited_by, mu.invited_by_group_member_id, mu.local_display_name, mu.contact_id, mu.contact_profile_id, pu.contact_profile_id, + mu.member_status, mu.show_messages, mu.member_restriction, mu.invited_by, mu.invited_by_group_member_id, mu.local_display_name, mu.contact_id, mu.contact_profile_id, pu.contact_profile_id, -- GroupInfo {membership = GroupMember {memberProfile}} pu.display_name, pu.full_name, pu.image, pu.contact_link, pu.local_alias, pu.preferences, -- from GroupMember - m.group_member_id, m.group_id, m.member_id, m.peer_chat_min_version, m.peer_chat_max_version, m.member_role, m.member_category, m.member_status, m.show_messages, + m.group_member_id, m.group_id, m.member_id, m.peer_chat_min_version, m.peer_chat_max_version, m.member_role, m.member_category, m.member_status, m.show_messages, m.member_restriction, m.invited_by, m.invited_by_group_member_id, m.local_display_name, m.contact_id, m.contact_profile_id, p.contact_profile_id, p.display_name, p.full_name, p.image, p.contact_link, p.local_alias, p.preferences FROM group_members m JOIN contact_profiles p ON p.contact_profile_id = COALESCE(m.member_profile_id, m.contact_profile_id) diff --git a/src/Simplex/Chat/Store/Direct.hs b/src/Simplex/Chat/Store/Direct.hs index b54a986d2b..43d58d3ffa 100644 --- a/src/Simplex/Chat/Store/Direct.hs +++ b/src/Simplex/Chat/Store/Direct.hs @@ -9,9 +9,13 @@ {-# OPTIONS_GHC -fno-warn-ambiguous-fields #-} module Simplex.Chat.Store.Direct - ( updateContact_, + ( updateContactLDN_, updateContactProfile_, updateContactProfile_', + updateMemberContactProfileReset_', + updateMemberContactProfileReset_, + updateMemberContactProfile_, + updateMemberContactProfile_', deleteContactProfile_, deleteUnusedProfile_, @@ -316,7 +320,7 @@ updateContactProfile db user@User {userId} c p' ExceptT . withLocalDisplayName db userId newName $ \ldn -> do currentTs <- getCurrentTime updateContactProfile_' db userId profileId p' currentTs - updateContact_ db userId contactId localDisplayName ldn currentTs + updateContactLDN_ db userId contactId localDisplayName ldn currentTs pure $ Right c {localDisplayName = ldn, profile, mergedPreferences} where Contact {contactId, localDisplayName, profile = LocalProfile {profileId, displayName, localAlias}, userPreferences} = c @@ -398,6 +402,7 @@ setUserChatsRead db User {userId} = do updatedAt <- getCurrentTime DB.execute db "UPDATE contacts SET unread_chat = ?, updated_at = ? WHERE user_id = ? AND unread_chat = ?" (False, updatedAt, userId, True) DB.execute db "UPDATE groups SET unread_chat = ?, updated_at = ? WHERE user_id = ? AND unread_chat = ?" (False, updatedAt, userId, True) + DB.execute db "UPDATE note_folders SET unread_chat = ?, updated_at = ? WHERE user_id = ? AND unread_chat = ?" (False, updatedAt, userId, True) DB.execute db "UPDATE chat_items SET item_status = ?, updated_at = ? WHERE user_id = ? AND item_status = ?" (CISRcvRead, updatedAt, userId, CISRcvNew) updateContactStatus :: DB.Connection -> User -> Contact -> ContactStatus -> IO Contact @@ -452,8 +457,42 @@ updateContactProfile_' db userId profileId Profile {displayName, fullName, image |] (displayName, fullName, image, contactLink, preferences, updatedAt, userId, profileId) -updateContact_ :: DB.Connection -> UserId -> Int64 -> ContactName -> ContactName -> UTCTime -> IO () -updateContact_ db userId contactId displayName newName updatedAt = do +-- update only member profile fields (when member doesn't have associated contact - we can reset contactLink and prefs) +updateMemberContactProfileReset_ :: DB.Connection -> UserId -> ProfileId -> Profile -> IO () +updateMemberContactProfileReset_ db userId profileId profile = do + currentTs <- getCurrentTime + updateMemberContactProfileReset_' db userId profileId profile currentTs + +updateMemberContactProfileReset_' :: DB.Connection -> UserId -> ProfileId -> Profile -> UTCTime -> IO () +updateMemberContactProfileReset_' db userId profileId Profile {displayName, fullName, image} updatedAt = do + DB.execute + db + [sql| + UPDATE contact_profiles + SET display_name = ?, full_name = ?, image = ?, contact_link = NULL, preferences = NULL, updated_at = ? + WHERE user_id = ? AND contact_profile_id = ? + |] + (displayName, fullName, image, updatedAt, userId, profileId) + +-- update only member profile fields (when member has associated contact - we keep contactLink and prefs) +updateMemberContactProfile_ :: DB.Connection -> UserId -> ProfileId -> Profile -> IO () +updateMemberContactProfile_ db userId profileId profile = do + currentTs <- getCurrentTime + updateMemberContactProfile_' db userId profileId profile currentTs + +updateMemberContactProfile_' :: DB.Connection -> UserId -> ProfileId -> Profile -> UTCTime -> IO () +updateMemberContactProfile_' db userId profileId Profile {displayName, fullName, image} updatedAt = do + DB.execute + db + [sql| + UPDATE contact_profiles + SET display_name = ?, full_name = ?, image = ?, updated_at = ? + WHERE user_id = ? AND contact_profile_id = ? + |] + (displayName, fullName, image, updatedAt, userId, profileId) + +updateContactLDN_ :: DB.Connection -> UserId -> Int64 -> ContactName -> ContactName -> UTCTime -> IO () +updateContactLDN_ db userId contactId displayName newName updatedAt = do DB.execute db "UPDATE contacts SET local_display_name = ?, updated_at = ? WHERE user_id = ? AND contact_id = ?" @@ -488,7 +527,7 @@ createOrUpdateContactRequest db user@User {userId} userContactLinkId invId (Vers ExceptT $ maybeM getContactRequestByXContactId xContactId_ >>= \case Nothing -> createContactRequest - Just cr -> updateContactRequest cr $> Right (contactRequestId (cr :: UserContactRequest)) + Just cr@UserContactRequest {contactRequestId} -> updateContactRequest cr $> Right contactRequestId getContactRequest db user cReqId createContactRequest :: IO (Either StoreError Int64) createContactRequest = do diff --git a/src/Simplex/Chat/Store/Files.hs b/src/Simplex/Chat/Store/Files.hs index abc368e9a3..bc5cec3332 100644 --- a/src/Simplex/Chat/Store/Files.hs +++ b/src/Simplex/Chat/Store/Files.hs @@ -1,4 +1,5 @@ {-# LANGUAGE DuplicateRecordFields #-} +{-# LANGUAGE FlexibleContexts #-} {-# LANGUAGE GADTs #-} {-# LANGUAGE LambdaCase #-} {-# LANGUAGE NamedFieldPuns #-} @@ -72,7 +73,10 @@ module Simplex.Chat.Store.Files getSndFileTransfer, getSndFileTransfers, getContactFileInfo, + getNoteFolderFileInfo, + createLocalFile, getLocalCryptoFile, + getLocalFileMeta, updateDirectCIFileStatus, ) where @@ -90,6 +94,7 @@ import Data.Time.Clock (UTCTime (..), getCurrentTime, nominalDay) import Data.Type.Equality import Database.SQLite.Simple (Only (..), (:.) (..)) import Database.SQLite.Simple.QQ (sql) +import Database.SQLite.Simple.ToField (ToField) import Simplex.Chat.Messages import Simplex.Chat.Messages.CIContent import Simplex.Chat.Protocol @@ -107,6 +112,7 @@ import Simplex.Messaging.Crypto.File (CryptoFile (..), CryptoFileArgs (..)) import qualified Simplex.Messaging.Crypto.File as CF import Simplex.Messaging.Protocol (SubscriptionMode (..)) import Simplex.Messaging.Version (VersionRange) +import System.FilePath (takeFileName) getLiveSndFileTransfers :: DB.Connection -> User -> IO [SndFileTransfer] getLiveSndFileTransfers db User {userId} = do @@ -492,7 +498,7 @@ createRcvFileTransfer :: DB.Connection -> UserId -> Contact -> FileInvitation -> createRcvFileTransfer db userId Contact {contactId, localDisplayName = c} f@FileInvitation {fileName, fileSize, fileConnReq, fileInline, fileDescr} rcvFileInline chunkSize = do currentTs <- liftIO getCurrentTime rfd_ <- mapM (createRcvFD_ db userId currentTs) fileDescr - let rfdId = (fileDescrId :: RcvFileDescr -> Int64) <$> rfd_ + let rfdId = (\RcvFileDescr {fileDescrId} -> fileDescrId) <$> rfd_ -- cryptoArgs = Nothing here, the decision to encrypt is made when receiving it xftpRcvFile = (\rfd -> XFTPRcvFile {rcvFileDescription = rfd, agentRcvFileId = Nothing, agentRcvFileDeleted = False}) <$> rfd_ fileProtocol = if isJust rfd_ then FPXFTP else FPSMP @@ -513,7 +519,7 @@ createRcvGroupFileTransfer :: DB.Connection -> UserId -> GroupMember -> FileInvi createRcvGroupFileTransfer db userId GroupMember {groupId, groupMemberId, localDisplayName = c} f@FileInvitation {fileName, fileSize, fileConnReq, fileInline, fileDescr} rcvFileInline chunkSize = do currentTs <- liftIO getCurrentTime rfd_ <- mapM (createRcvFD_ db userId currentTs) fileDescr - let rfdId = (fileDescrId :: RcvFileDescr -> Int64) <$> rfd_ + let rfdId = (\RcvFileDescr {fileDescrId} -> fileDescrId) <$> rfd_ -- cryptoArgs = Nothing here, the decision to encrypt is made when receiving it xftpRcvFile = (\rfd -> XFTPRcvFile {rcvFileDescription = rfd, agentRcvFileId = Nothing, agentRcvFileDeleted = False}) <$> rfd_ fileProtocol = if isJust rfd_ then FPXFTP else FPSMP @@ -839,18 +845,19 @@ getFileTransfer :: DB.Connection -> User -> Int64 -> ExceptT StoreError IO FileT getFileTransfer db user@User {userId} fileId = fileTransfer =<< liftIO (getFileTransferRow_ db userId fileId) where - fileTransfer :: [(Maybe Int64, Maybe Int64)] -> ExceptT StoreError IO FileTransfer - fileTransfer [(Nothing, Just _)] = FTRcv <$> getRcvFileTransfer db user fileId + fileTransfer :: [(Maybe Int64, Maybe Int64, FileProtocol)] -> ExceptT StoreError IO FileTransfer + fileTransfer [(_, _, FPLocal)] = throwError $ SELocalFileNoTransfer fileId + fileTransfer [(Nothing, Just _, _)] = FTRcv <$> getRcvFileTransfer db user fileId fileTransfer _ = do (ftm, fts) <- getSndFileTransfer db user fileId pure $ FTSnd {fileTransferMeta = ftm, sndFileTransfers = fts} -getFileTransferRow_ :: DB.Connection -> UserId -> Int64 -> IO [(Maybe Int64, Maybe Int64)] +getFileTransferRow_ :: DB.Connection -> UserId -> Int64 -> IO [(Maybe Int64, Maybe Int64, FileProtocol)] getFileTransferRow_ db userId fileId = DB.query db [sql| - SELECT s.file_id, r.file_id + SELECT s.file_id, r.file_id, f.protocol FROM files f LEFT JOIN snd_files s ON s.file_id = f.file_id LEFT JOIN rcv_files r ON r.file_id = f.file_id @@ -911,24 +918,70 @@ getFileTransferMeta_ db userId fileId = xftpSndFile = (\fId -> XFTPSndFile {agentSndFileId = fId, privateSndFileDescr, agentSndFileDeleted, cryptoArgs}) <$> aSndFileId_ in FileTransferMeta {fileId, xftpSndFile, fileName, fileSize, chunkSize, filePath, fileInline, cancelled = fromMaybe False cancelled_} +createLocalFile :: ToField (CIFileStatus d) => CIFileStatus d -> DB.Connection -> User -> NoteFolder -> ChatItemId -> UTCTime -> CryptoFile -> Integer -> Integer -> IO Int64 +createLocalFile fileStatus db User {userId} NoteFolder {noteFolderId} chatItemId itemTs CryptoFile {filePath, cryptoArgs} fileSize fileChunkSize = do + DB.execute + db + [sql| + INSERT INTO files + ( user_id, note_folder_id, chat_item_id, + file_name, file_path, file_size, + file_crypto_key, file_crypto_nonce, + chunk_size, file_inline, ci_file_status, protocol, created_at, updated_at + ) + VALUES (?,?,?,?,?,?,?,?,?,?,?,?,?,?) + |] + ( (userId, noteFolderId, chatItemId) + :. (takeFileName filePath, filePath, fileSize) + :. maybe (Nothing, Nothing) (\(CFArgs key nonce) -> (Just key, Just nonce)) cryptoArgs + :. (fileChunkSize, Nothing :: Maybe InlineFileMode, fileStatus, FPLocal, itemTs, itemTs) + ) + insertedRowId db + +getLocalFileMeta :: DB.Connection -> UserId -> Int64 -> ExceptT StoreError IO LocalFileMeta +getLocalFileMeta db userId fileId = + ExceptT . firstRow localFileMeta (SEFileNotFound fileId) $ + DB.query + db + [sql| + SELECT file_name, file_size, file_path, file_crypto_key, file_crypto_nonce + FROM files + WHERE user_id = ? AND file_id = ? + |] + (userId, fileId) + where + localFileMeta :: (FilePath, Integer, FilePath, Maybe C.SbKey, Maybe C.CbNonce) -> LocalFileMeta + localFileMeta (fileName, fileSize, filePath, fileKey, fileNonce) = + let fileCryptoArgs = CFArgs <$> fileKey <*> fileNonce + in LocalFileMeta {fileId, fileName, fileSize, filePath, fileCryptoArgs} + getContactFileInfo :: DB.Connection -> User -> Contact -> IO [CIFileInfo] getContactFileInfo db User {userId} Contact {contactId} = map toFileInfo <$> DB.query db (fileInfoQuery <> " WHERE i.user_id = ? AND i.contact_id = ?") (userId, contactId) +getNoteFolderFileInfo :: DB.Connection -> User -> NoteFolder -> IO [CIFileInfo] +getNoteFolderFileInfo db User {userId} NoteFolder {noteFolderId} = + map toFileInfo + <$> DB.query db (fileInfoQuery <> " WHERE i.user_id = ? AND i.note_folder_id = ?") (userId, noteFolderId) + getLocalCryptoFile :: DB.Connection -> UserId -> Int64 -> Bool -> ExceptT StoreError IO CryptoFile getLocalCryptoFile db userId fileId sent = liftIO (getFileTransferRow_ db userId fileId) >>= \case - [(Nothing, Just _)] -> do + [(Nothing, Just _, _)] -> do when sent $ throwError $ SEFileNotFound fileId RcvFileTransfer {fileStatus, cryptoArgs} <- getRcvFileTransfer_ db userId fileId case fileStatus of RFSComplete RcvFileInfo {filePath} -> pure $ CryptoFile filePath cryptoArgs _ -> throwError $ SEFileNotFound fileId - _ -> do + [(Just _, Nothing, _)] -> do unless sent $ throwError $ SEFileNotFound fileId FileTransferMeta {filePath, xftpSndFile} <- getFileTransferMeta_ db userId fileId pure $ CryptoFile filePath $ xftpSndFile >>= \XFTPSndFile {cryptoArgs} -> cryptoArgs + [(Nothing, Nothing, FPLocal)] -> do + LocalFileMeta {filePath, fileCryptoArgs} <- getLocalFileMeta db userId fileId + pure $ CryptoFile filePath fileCryptoArgs + _ -> throwError $ SEFileNotFound fileId updateDirectCIFileStatus :: forall d. MsgDirectionI d => DB.Connection -> VersionRange -> User -> Int64 -> CIFileStatus d -> ExceptT StoreError IO AChatItem updateDirectCIFileStatus db vr user fileId fileStatus = do diff --git a/src/Simplex/Chat/Store/Groups.hs b/src/Simplex/Chat/Store/Groups.hs index ddb97e590a..189f95fdf0 100644 --- a/src/Simplex/Chat/Store/Groups.hs +++ b/src/Simplex/Chat/Store/Groups.hs @@ -98,6 +98,7 @@ module Simplex.Chat.Store.Groups deleteOldProbes, updateGroupSettings, updateGroupMemberSettings, + updateGroupMemberBlocked, getXGrpMemIntroContDirect, getXGrpMemIntroContGroup, getHostConnId, @@ -108,8 +109,12 @@ module Simplex.Chat.Store.Groups updateMemberContactInvited, resetMemberContactFields, updateMemberProfile, + updateContactMemberProfile, getXGrpLinkMemReceived, setXGrpLinkMemReceived, + createNewUnknownGroupMember, + updateUnknownMemberAnnounced, + updateUserMemberProfileSentAt, ) where @@ -141,32 +146,33 @@ import Simplex.Messaging.Util (eitherToMaybe, ($>>=), (<$$>)) import Simplex.Messaging.Version import UnliftIO.STM -type GroupInfoRow = (Int64, GroupName, GroupName, Text, Maybe Text, Maybe ImageData, Maybe ProfileId, Maybe MsgFilter, Maybe Bool, Bool, Maybe GroupPreferences) :. (UTCTime, UTCTime, Maybe UTCTime) :. GroupMemberRow +type GroupInfoRow = (Int64, GroupName, GroupName, Text, Maybe Text, Maybe ImageData, Maybe ProfileId, Maybe MsgFilter, Maybe Bool, Bool, Maybe GroupPreferences) :. (UTCTime, UTCTime, Maybe UTCTime, Maybe UTCTime) :. GroupMemberRow -type GroupMemberRow = ((Int64, Int64, MemberId, Version, Version, GroupMemberRole, GroupMemberCategory, GroupMemberStatus, Bool) :. (Maybe Int64, Maybe GroupMemberId, ContactName, Maybe ContactId, ProfileId, ProfileId, ContactName, Text, Maybe ImageData, Maybe ConnReqContact, LocalAlias, Maybe Preferences)) +type GroupMemberRow = ((Int64, Int64, MemberId, Version, Version, GroupMemberRole, GroupMemberCategory, GroupMemberStatus, Bool, Maybe MemberRestrictionStatus) :. (Maybe Int64, Maybe GroupMemberId, ContactName, Maybe ContactId, ProfileId, ProfileId, ContactName, Text, Maybe ImageData, Maybe ConnReqContact, LocalAlias, Maybe Preferences)) -type MaybeGroupMemberRow = ((Maybe Int64, Maybe Int64, Maybe MemberId, Maybe Version, Maybe Version, Maybe GroupMemberRole, Maybe GroupMemberCategory, Maybe GroupMemberStatus, Maybe Bool) :. (Maybe Int64, Maybe GroupMemberId, Maybe ContactName, Maybe ContactId, Maybe ProfileId, Maybe ProfileId, Maybe ContactName, Maybe Text, Maybe ImageData, Maybe ConnReqContact, Maybe LocalAlias, Maybe Preferences)) +type MaybeGroupMemberRow = ((Maybe Int64, Maybe Int64, Maybe MemberId, Maybe Version, Maybe Version, Maybe GroupMemberRole, Maybe GroupMemberCategory, Maybe GroupMemberStatus, Maybe Bool, Maybe MemberRestrictionStatus) :. (Maybe Int64, Maybe GroupMemberId, Maybe ContactName, Maybe ContactId, Maybe ProfileId, Maybe ProfileId, Maybe ContactName, Maybe Text, Maybe ImageData, Maybe ConnReqContact, Maybe LocalAlias, Maybe Preferences)) toGroupInfo :: VersionRange -> Int64 -> GroupInfoRow -> GroupInfo -toGroupInfo vr userContactId ((groupId, localDisplayName, displayName, fullName, description, image, hostConnCustomUserProfileId, enableNtfs_, sendRcpts, favorite, groupPreferences) :. (createdAt, updatedAt, chatTs) :. userMemberRow) = +toGroupInfo vr userContactId ((groupId, localDisplayName, displayName, fullName, description, image, hostConnCustomUserProfileId, enableNtfs_, sendRcpts, favorite, groupPreferences) :. (createdAt, updatedAt, chatTs, userMemberProfileSentAt) :. userMemberRow) = let membership = (toGroupMember userContactId userMemberRow) {memberChatVRange = JVersionRange vr} chatSettings = ChatSettings {enableNtfs = fromMaybe MFAll enableNtfs_, sendRcpts, favorite} fullGroupPreferences = mergeGroupPreferences groupPreferences groupProfile = GroupProfile {displayName, fullName, description, image, groupPreferences} - in GroupInfo {groupId, localDisplayName, groupProfile, fullGroupPreferences, membership, hostConnCustomUserProfileId, chatSettings, createdAt, updatedAt, chatTs} + in GroupInfo {groupId, localDisplayName, groupProfile, fullGroupPreferences, membership, hostConnCustomUserProfileId, chatSettings, createdAt, updatedAt, chatTs, userMemberProfileSentAt} toGroupMember :: Int64 -> GroupMemberRow -> GroupMember -toGroupMember userContactId ((groupMemberId, groupId, memberId, minVer, maxVer, memberRole, memberCategory, memberStatus, showMessages) :. (invitedById, invitedByGroupMemberId, localDisplayName, memberContactId, memberContactProfileId, profileId, displayName, fullName, image, contactLink, localAlias, preferences)) = +toGroupMember userContactId ((groupMemberId, groupId, memberId, minVer, maxVer, memberRole, memberCategory, memberStatus, showMessages, memberRestriction_) :. (invitedById, invitedByGroupMemberId, localDisplayName, memberContactId, memberContactProfileId, profileId, displayName, fullName, image, contactLink, localAlias, preferences)) = let memberProfile = LocalProfile {profileId, displayName, fullName, image, contactLink, preferences, localAlias} memberSettings = GroupMemberSettings {showMessages} + blockedByAdmin = maybe False mrsBlocked memberRestriction_ invitedBy = toInvitedBy userContactId invitedById activeConn = Nothing memberChatVRange = JVersionRange $ fromMaybe (versionToRange maxVer) $ safeVersionRange minVer maxVer in GroupMember {..} toMaybeGroupMember :: Int64 -> MaybeGroupMemberRow -> Maybe GroupMember -toMaybeGroupMember userContactId ((Just groupMemberId, Just groupId, Just memberId, Just minVer, Just maxVer, Just memberRole, Just memberCategory, Just memberStatus, Just showMessages) :. (invitedById, invitedByGroupMemberId, Just localDisplayName, memberContactId, Just memberContactProfileId, Just profileId, Just displayName, Just fullName, image, contactLink, Just localAlias, contactPreferences)) = - Just $ toGroupMember userContactId ((groupMemberId, groupId, memberId, minVer, maxVer, memberRole, memberCategory, memberStatus, showMessages) :. (invitedById, invitedByGroupMemberId, localDisplayName, memberContactId, memberContactProfileId, profileId, displayName, fullName, image, contactLink, localAlias, contactPreferences)) +toMaybeGroupMember userContactId ((Just groupMemberId, Just groupId, Just memberId, Just minVer, Just maxVer, Just memberRole, Just memberCategory, Just memberStatus, Just showMessages, memberBlocked) :. (invitedById, invitedByGroupMemberId, Just localDisplayName, memberContactId, Just memberContactProfileId, Just profileId, Just displayName, Just fullName, image, contactLink, Just localAlias, contactPreferences)) = + Just $ toGroupMember userContactId ((groupMemberId, groupId, memberId, minVer, maxVer, memberRole, memberCategory, memberStatus, showMessages, memberBlocked) :. (invitedById, invitedByGroupMemberId, localDisplayName, memberContactId, memberContactProfileId, profileId, displayName, fullName, image, contactLink, localAlias, contactPreferences)) toMaybeGroupMember _ _ = Nothing createGroupLink :: DB.Connection -> User -> GroupInfo -> ConnId -> ConnReqContact -> GroupLinkId -> GroupMemberRole -> SubscriptionMode -> ExceptT StoreError IO () @@ -259,14 +265,16 @@ getGroupAndMember db User {userId, userContactId} groupMemberId vr = [sql| SELECT -- GroupInfo - g.group_id, g.local_display_name, gp.display_name, gp.full_name, gp.description, gp.image, g.host_conn_custom_user_profile_id, g.enable_ntfs, g.send_rcpts, g.favorite, gp.preferences, g.created_at, g.updated_at, g.chat_ts, + g.group_id, g.local_display_name, gp.display_name, gp.full_name, gp.description, gp.image, + g.host_conn_custom_user_profile_id, g.enable_ntfs, g.send_rcpts, g.favorite, gp.preferences, + g.created_at, g.updated_at, g.chat_ts, g.user_member_profile_sent_at, -- GroupInfo {membership} mu.group_member_id, mu.group_id, mu.member_id, mu.peer_chat_min_version, mu.peer_chat_max_version, mu.member_role, mu.member_category, - mu.member_status, mu.show_messages, mu.invited_by, mu.invited_by_group_member_id, mu.local_display_name, mu.contact_id, mu.contact_profile_id, pu.contact_profile_id, + mu.member_status, mu.show_messages, mu.member_restriction, mu.invited_by, mu.invited_by_group_member_id, mu.local_display_name, mu.contact_id, mu.contact_profile_id, pu.contact_profile_id, -- GroupInfo {membership = GroupMember {memberProfile}} pu.display_name, pu.full_name, pu.image, pu.contact_link, pu.local_alias, pu.preferences, -- from GroupMember - m.group_member_id, m.group_id, m.member_id, m.peer_chat_min_version, m.peer_chat_max_version, m.member_role, m.member_category, m.member_status, m.show_messages, + m.group_member_id, m.group_id, m.member_id, m.peer_chat_min_version, m.peer_chat_max_version, m.member_role, m.member_category, m.member_status, m.show_messages, m.member_restriction, m.invited_by, m.invited_by_group_member_id, m.local_display_name, m.contact_id, m.contact_profile_id, p.contact_profile_id, p.display_name, p.full_name, p.image, p.contact_link, p.local_alias, p.preferences, c.connection_id, c.agent_conn_id, c.conn_level, c.via_contact, c.via_user_contact_link, c.via_group_link, c.group_link_id, c.custom_user_profile_id, c.conn_status, c.conn_type, c.contact_conn_initiated, c.local_alias, c.contact_id, c.group_member_id, c.snd_file_id, c.rcv_file_id, c.user_contact_link_id, c.created_at, c.security_code, c.security_code_verified_at, c.auth_err_counter, @@ -308,18 +316,36 @@ createNewGroup db vr gVar user@User {userId} groupProfile incognitoProfile = Exc profileId <- insertedRowId db DB.execute db - "INSERT INTO groups (local_display_name, user_id, group_profile_id, enable_ntfs, created_at, updated_at, chat_ts) VALUES (?,?,?,?,?,?,?)" - (ldn, userId, profileId, True, currentTs, currentTs, currentTs) + [sql| + INSERT INTO groups + (local_display_name, user_id, group_profile_id, enable_ntfs, + created_at, updated_at, chat_ts, user_member_profile_sent_at) + VALUES (?,?,?,?,?,?,?,?) + |] + (ldn, userId, profileId, True, currentTs, currentTs, currentTs, currentTs) insertedRowId db memberId <- liftIO $ encodedRandomBytes gVar 12 membership <- createContactMemberInv_ db user groupId Nothing user (MemberIdRole (MemberId memberId) GROwner) GCUserMember GSMemCreator IBUser customUserProfileId currentTs vr let chatSettings = ChatSettings {enableNtfs = MFAll, sendRcpts = Nothing, favorite = False} - pure GroupInfo {groupId, localDisplayName = ldn, groupProfile, fullGroupPreferences, membership, hostConnCustomUserProfileId = Nothing, chatSettings, createdAt = currentTs, updatedAt = currentTs, chatTs = Just currentTs} + pure + GroupInfo + { groupId, + localDisplayName = ldn, + groupProfile, + fullGroupPreferences, + membership, + hostConnCustomUserProfileId = Nothing, + chatSettings, + createdAt = currentTs, + updatedAt = currentTs, + chatTs = Just currentTs, + userMemberProfileSentAt = Just currentTs + } -- | creates a new group record for the group the current user was invited to, or returns an existing one createGroupInvitation :: DB.Connection -> VersionRange -> User -> Contact -> GroupInvitation -> Maybe ProfileId -> ExceptT StoreError IO (GroupInfo, GroupMemberId) createGroupInvitation _ _ _ Contact {localDisplayName, activeConn = Nothing} _ _ = throwError $ SEContactNotReady localDisplayName -createGroupInvitation db vr user@User {userId} contact@Contact {contactId, activeConn = Just hostConn@Connection {customUserProfileId}} GroupInvitation {fromMember, invitedMember, connRequest, groupProfile} incognitoProfileId = do +createGroupInvitation db vr user@User {userId} contact@Contact {contactId, activeConn = Just Connection {customUserProfileId, peerChatVRange}} GroupInvitation {fromMember, invitedMember, connRequest, groupProfile} incognitoProfileId = do liftIO getInvitationGroupId_ >>= \case Nothing -> createGroupInvitation_ Just gId -> do @@ -354,14 +380,34 @@ createGroupInvitation db vr user@User {userId} contact@Contact {contactId, activ profileId <- insertedRowId db DB.execute db - "INSERT INTO groups (group_profile_id, local_display_name, inv_queue_info, host_conn_custom_user_profile_id, user_id, enable_ntfs, created_at, updated_at, chat_ts) VALUES (?,?,?,?,?,?,?,?,?)" - (profileId, localDisplayName, connRequest, customUserProfileId, userId, True, currentTs, currentTs, currentTs) + [sql| + INSERT INTO groups + (group_profile_id, local_display_name, inv_queue_info, host_conn_custom_user_profile_id, user_id, enable_ntfs, + created_at, updated_at, chat_ts, user_member_profile_sent_at) + VALUES (?,?,?,?,?,?,?,?,?,?) + |] + (profileId, localDisplayName, connRequest, customUserProfileId, userId, True, currentTs, currentTs, currentTs, currentTs) insertedRowId db - let JVersionRange hostVRange = peerChatVRange hostConn + let JVersionRange hostVRange = peerChatVRange GroupMember {groupMemberId} <- createContactMemberInv_ db user groupId Nothing contact fromMember GCHostMember GSMemInvited IBUnknown Nothing currentTs hostVRange membership <- createContactMemberInv_ db user groupId (Just groupMemberId) user invitedMember GCUserMember GSMemInvited (IBContact contactId) incognitoProfileId currentTs vr let chatSettings = ChatSettings {enableNtfs = MFAll, sendRcpts = Nothing, favorite = False} - pure (GroupInfo {groupId, localDisplayName, groupProfile, fullGroupPreferences, membership, hostConnCustomUserProfileId = customUserProfileId, chatSettings, createdAt = currentTs, updatedAt = currentTs, chatTs = Just currentTs}, groupMemberId) + pure + ( GroupInfo + { groupId, + localDisplayName, + groupProfile, + fullGroupPreferences, + membership, + hostConnCustomUserProfileId = customUserProfileId, + chatSettings, + createdAt = currentTs, + updatedAt = currentTs, + chatTs = Just currentTs, + userMemberProfileSentAt = Just currentTs + }, + groupMemberId + ) getHostMemberId_ :: DB.Connection -> User -> GroupId -> ExceptT StoreError IO GroupMemberId getHostMemberId_ db User {userId} groupId = @@ -385,6 +431,7 @@ createContactMemberInv_ db User {userId, userContactId} groupId invitedByGroupMe memberCategory, memberStatus, memberSettings = defaultMemberSettings, + blockedByAdmin = False, invitedBy, invitedByGroupMemberId, localDisplayName, @@ -455,29 +502,33 @@ createGroupInvitedViaLink "INSERT INTO group_profiles (display_name, full_name, description, image, user_id, preferences, created_at, updated_at) VALUES (?,?,?,?,?,?,?,?)" (displayName, fullName, description, image, userId, groupPreferences, currentTs, currentTs) profileId <- insertedRowId db - DB.execute - db - "INSERT INTO groups (group_profile_id, local_display_name, host_conn_custom_user_profile_id, user_id, enable_ntfs, created_at, updated_at, chat_ts) VALUES (?,?,?,?,?,?,?,?)" - (profileId, localDisplayName, customUserProfileId, userId, True, currentTs, currentTs, currentTs) - insertedRowId db - insertHost_ currentTs groupId = ExceptT $ do - let fromMemberProfile = profileFromName fromMemberName - withLocalDisplayName db userId fromMemberName $ \localDisplayName -> runExceptT $ do - (_, profileId) <- createNewMemberProfile_ db user fromMemberProfile currentTs - let MemberIdRole {memberId, memberRole} = fromMember - liftIO $ do DB.execute db [sql| - INSERT INTO group_members - ( group_id, member_id, member_role, member_category, member_status, invited_by, - user_id, local_display_name, contact_id, contact_profile_id, created_at, updated_at) - VALUES (?,?,?,?,?,?,?,?,?,?,?,?) + INSERT INTO groups + (group_profile_id, local_display_name, host_conn_custom_user_profile_id, user_id, enable_ntfs, + created_at, updated_at, chat_ts, user_member_profile_sent_at) + VALUES (?,?,?,?,?,?,?,?,?) |] - ( (groupId, memberId, memberRole, GCHostMember, GSMemAccepted, fromInvitedBy userContactId IBUnknown) - :. (userId, localDisplayName, Nothing :: (Maybe Int64), profileId, currentTs, currentTs) - ) + (profileId, localDisplayName, customUserProfileId, userId, True, currentTs, currentTs, currentTs, currentTs) insertedRowId db + insertHost_ currentTs groupId = do + let fromMemberProfile = profileFromName fromMemberName + (localDisplayName, profileId) <- createNewMemberProfile_ db user fromMemberProfile currentTs + let MemberIdRole {memberId, memberRole} = fromMember + liftIO $ do + DB.execute + db + [sql| + INSERT INTO group_members + ( group_id, member_id, member_role, member_category, member_status, invited_by, + user_id, local_display_name, contact_id, contact_profile_id, created_at, updated_at) + VALUES (?,?,?,?,?,?,?,?,?,?,?,?) + |] + ( (groupId, memberId, memberRole, GCHostMember, GSMemAccepted, fromInvitedBy userContactId IBUnknown) + :. (userId, localDisplayName, Nothing :: (Maybe Int64), profileId, currentTs, currentTs) + ) + insertedRowId db setViaGroupLinkHash :: DB.Connection -> GroupId -> Int64 -> IO () setViaGroupLinkHash db groupId connId = @@ -563,8 +614,11 @@ getUserGroupDetails db vr User {userId, userContactId} _contactId_ search_ = <$> DB.query db [sql| - SELECT g.group_id, g.local_display_name, gp.display_name, gp.full_name, gp.description, gp.image, g.host_conn_custom_user_profile_id, g.enable_ntfs, g.send_rcpts, g.favorite, gp.preferences, g.created_at, g.updated_at, g.chat_ts, - mu.group_member_id, g.group_id, mu.member_id, mu.peer_chat_min_version, mu.peer_chat_max_version, mu.member_role, mu.member_category, mu.member_status, mu.show_messages, + SELECT + g.group_id, g.local_display_name, gp.display_name, gp.full_name, gp.description, gp.image, + g.host_conn_custom_user_profile_id, g.enable_ntfs, g.send_rcpts, g.favorite, gp.preferences, + g.created_at, g.updated_at, g.chat_ts, g.user_member_profile_sent_at, + mu.group_member_id, g.group_id, mu.member_id, mu.peer_chat_min_version, mu.peer_chat_max_version, mu.member_role, mu.member_category, mu.member_status, mu.show_messages, mu.member_restriction, mu.invited_by, mu.invited_by_group_member_id, mu.local_display_name, mu.contact_id, mu.contact_profile_id, pu.contact_profile_id, pu.display_name, pu.full_name, pu.image, pu.contact_link, pu.local_alias, pu.preferences FROM groups g JOIN group_profiles gp USING (group_profile_id) @@ -595,11 +649,9 @@ getGroupSummary db User {userId} groupId = do JOIN group_members m USING (group_id) WHERE g.user_id = ? AND g.group_id = ? - AND m.member_status != ? - AND m.member_status != ? - AND m.member_status != ? + AND m.member_status NOT IN (?,?,?,?) |] - (userId, groupId, GSMemRemoved, GSMemLeft, GSMemInvited) + (userId, groupId, GSMemRemoved, GSMemLeft, GSMemUnknown, GSMemInvited) pure GroupSummary {currentMembers = fromMaybe 0 currentMembers_} getContactGroupPreferences :: DB.Connection -> User -> Contact -> IO [FullGroupPreferences] @@ -629,7 +681,7 @@ groupMemberQuery :: Query groupMemberQuery = [sql| SELECT - m.group_member_id, m.group_id, m.member_id, m.peer_chat_min_version, m.peer_chat_max_version, m.member_role, m.member_category, m.member_status, m.show_messages, + m.group_member_id, m.group_id, m.member_id, m.peer_chat_min_version, m.peer_chat_max_version, m.member_role, m.member_category, m.member_status, m.show_messages, m.member_restriction, m.invited_by, m.invited_by_group_member_id, m.local_display_name, m.contact_id, m.contact_profile_id, p.contact_profile_id, p.display_name, p.full_name, p.image, p.contact_link, p.local_alias, p.preferences, c.connection_id, c.agent_conn_id, c.conn_level, c.via_contact, c.via_user_contact_link, c.via_group_link, c.group_link_id, c.custom_user_profile_id, c.conn_status, c.conn_type, c.contact_conn_initiated, c.local_alias, c.contact_id, c.group_member_id, c.snd_file_id, c.rcv_file_id, c.user_contact_link_id, c.created_at, c.security_code, c.security_code_verified_at, c.auth_err_counter, @@ -683,13 +735,13 @@ getGroupMembersForExpiration db user@User {userId, userContactId} GroupInfo {gro ( groupMemberQuery <> [sql| WHERE m.group_id = ? AND m.user_id = ? AND (m.contact_id IS NULL OR m.contact_id != ?) - AND m.member_status IN (?, ?, ?) + AND m.member_status IN (?, ?, ?, ?) AND m.group_member_id NOT IN ( SELECT DISTINCT group_member_id FROM chat_items ) |] ) - (userId, groupId, userId, userContactId, GSMemRemoved, GSMemLeft, GSMemGroupDeleted) + (userId, groupId, userId, userContactId, GSMemRemoved, GSMemLeft, GSMemGroupDeleted, GSMemUnknown) toContactMember :: User -> (GroupMemberRow :. MaybeConnectionRow) -> GroupMember toContactMember User {userContactId} (memberRow :. connRow) = @@ -748,6 +800,7 @@ createNewContactMember db gVar User {userId, userContactId} GroupInfo {groupId, memberCategory = GCInviteeMember, memberStatus = GSMemInvited, memberSettings = defaultMemberSettings, + blockedByAdmin = False, invitedBy = IBUser, invitedByGroupMemberId = Just invitedByGroupMemberId, localDisplayName, @@ -905,6 +958,7 @@ createNewGroupMember db user gInfo invitingMember memInfo@MemberInfo {profile} m { memInfo, memCategory, memStatus, + memRestriction = Nothing, memInvitedBy = IBUnknown, memInvitedByGroupMemberId = Just $ groupMemberId' invitingMember, localDisplayName, @@ -932,6 +986,7 @@ createNewMember_ { memInfo = MemberInfo memberId memberRole memChatVRange memberProfile, memCategory = memberCategory, memStatus = memberStatus, + memRestriction, memInvitedBy = invitedBy, memInvitedByGroupMemberId, localDisplayName, @@ -946,12 +1001,12 @@ createNewMember_ db [sql| INSERT INTO group_members - (group_id, member_id, member_role, member_category, member_status, invited_by, invited_by_group_member_id, + (group_id, member_id, member_role, member_category, member_status, member_restriction, invited_by, invited_by_group_member_id, user_id, local_display_name, contact_id, contact_profile_id, created_at, updated_at, peer_chat_min_version, peer_chat_max_version) - VALUES (?,?,?,?,?,?,?,?,?,?,?,?,?,?,?) + VALUES (?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?) |] - ( (groupId, memberId, memberRole, memberCategory, memberStatus, invitedById, memInvitedByGroupMemberId) + ( (groupId, memberId, memberRole, memberCategory, memberStatus, memRestriction, invitedById, memInvitedByGroupMemberId) :. (userId, localDisplayName, memberContactId, memberContactProfileId, createdAt, createdAt) :. (minV, maxV) ) @@ -965,6 +1020,7 @@ createNewMember_ memberCategory, memberStatus, memberSettings = defaultMemberSettings, + blockedByAdmin = maybe False mrsBlocked memRestriction, invitedBy, invitedByGroupMemberId = memInvitedByGroupMemberId, localDisplayName, @@ -1040,7 +1096,7 @@ updateIntroStatus db introId introStatus = do [":intro_status" := introStatus, ":updated_at" := currentTs, ":intro_id" := introId] saveIntroInvitation :: DB.Connection -> GroupMember -> GroupMember -> IntroInvitation -> ExceptT StoreError IO GroupMemberIntro -saveIntroInvitation db reMember toMember introInv = do +saveIntroInvitation db reMember toMember introInv@IntroInvitation {groupConnReq} = do intro <- getIntroduction db reMember toMember liftIO $ do currentTs <- getCurrentTime @@ -1055,7 +1111,7 @@ saveIntroInvitation db reMember toMember introInv = do WHERE group_member_intro_id = :intro_id |] [ ":intro_status" := GMIntroInvReceived, - ":group_queue_info" := groupConnReq (introInv :: IntroInvitation), + ":group_queue_info" := groupConnReq, ":direct_queue_info" := directConnReq introInv, ":updated_at" := currentTs, ":intro_id" := introId intro @@ -1140,30 +1196,41 @@ getForwardInvitedMembers db user forwardMember highlyAvailable = do WHERE re_group_member_id = ? AND intro_status NOT IN (?,?,?) |] -createIntroReMember :: DB.Connection -> User -> GroupInfo -> GroupMember -> MemberInfo -> (CommandId, ConnId) -> Maybe (CommandId, ConnId) -> Maybe ProfileId -> SubscriptionMode -> ExceptT StoreError IO GroupMember -createIntroReMember db user@User {userId} gInfo@GroupInfo {groupId} _host@GroupMember {memberContactId, activeConn} memInfo@(MemberInfo _ _ memChatVRange memberProfile) (groupCmdId, groupAgentConnId) directConnIds customUserProfileId subMode = do - let mcvr = maybe chatInitialVRange fromChatVRange memChatVRange - cLevel = 1 + maybe 0 (\Connection {connLevel} -> connLevel) activeConn - currentTs <- liftIO getCurrentTime - newMember <- case directConnIds of - Just (directCmdId, directAgentConnId) -> do - Connection {connId = directConnId} <- liftIO $ createConnection_ db userId ConnContact Nothing directAgentConnId mcvr memberContactId Nothing customUserProfileId cLevel currentTs subMode - liftIO $ setCommandConnId db user directCmdId directConnId - (localDisplayName, contactId, memProfileId) <- createContact_ db userId memberProfile "" (Just groupId) currentTs False - liftIO $ DB.execute db "UPDATE connections SET contact_id = ?, updated_at = ? WHERE connection_id = ?" (contactId, currentTs, directConnId) - pure $ NewGroupMember {memInfo, memCategory = GCPreMember, memStatus = GSMemIntroduced, memInvitedBy = IBUnknown, memInvitedByGroupMemberId = Nothing, localDisplayName, memContactId = Just contactId, memProfileId} - Nothing -> do - (localDisplayName, memProfileId) <- createNewMemberProfile_ db user memberProfile currentTs - pure $ NewGroupMember {memInfo, memCategory = GCPreMember, memStatus = GSMemIntroduced, memInvitedBy = IBUnknown, memInvitedByGroupMemberId = Nothing, localDisplayName, memContactId = Nothing, memProfileId} - liftIO $ do - member <- createNewMember_ db user gInfo newMember currentTs - conn@Connection {connId = groupConnId} <- createMemberConnection_ db userId (groupMemberId' member) groupAgentConnId mcvr memberContactId cLevel currentTs subMode - liftIO $ setCommandConnId db user groupCmdId groupConnId - pure (member :: GroupMember) {activeConn = Just conn} +createIntroReMember :: DB.Connection -> User -> GroupInfo -> GroupMember -> MemberInfo -> Maybe MemberRestrictions -> (CommandId, ConnId) -> Maybe (CommandId, ConnId) -> Maybe ProfileId -> SubscriptionMode -> ExceptT StoreError IO GroupMember +createIntroReMember + db + user@User {userId} + gInfo@GroupInfo {groupId} + _host@GroupMember {memberContactId, activeConn} + memInfo@(MemberInfo _ _ memChatVRange memberProfile) + memRestrictions_ + (groupCmdId, groupAgentConnId) + directConnIds + customUserProfileId + subMode = do + let mcvr = maybe chatInitialVRange fromChatVRange memChatVRange + cLevel = 1 + maybe 0 (\Connection {connLevel} -> connLevel) activeConn + memRestriction = restriction <$> memRestrictions_ + currentTs <- liftIO getCurrentTime + newMember <- case directConnIds of + Just (directCmdId, directAgentConnId) -> do + Connection {connId = directConnId} <- liftIO $ createConnection_ db userId ConnContact Nothing directAgentConnId mcvr memberContactId Nothing customUserProfileId cLevel currentTs subMode + liftIO $ setCommandConnId db user directCmdId directConnId + (localDisplayName, contactId, memProfileId) <- createContact_ db userId memberProfile "" (Just groupId) currentTs False + liftIO $ DB.execute db "UPDATE connections SET contact_id = ?, updated_at = ? WHERE connection_id = ?" (contactId, currentTs, directConnId) + pure $ NewGroupMember {memInfo, memCategory = GCPreMember, memStatus = GSMemIntroduced, memRestriction, memInvitedBy = IBUnknown, memInvitedByGroupMemberId = Nothing, localDisplayName, memContactId = Just contactId, memProfileId} + Nothing -> do + (localDisplayName, memProfileId) <- createNewMemberProfile_ db user memberProfile currentTs + pure $ NewGroupMember {memInfo, memCategory = GCPreMember, memStatus = GSMemIntroduced, memRestriction, memInvitedBy = IBUnknown, memInvitedByGroupMemberId = Nothing, localDisplayName, memContactId = Nothing, memProfileId} + liftIO $ do + member <- createNewMember_ db user gInfo newMember currentTs + conn@Connection {connId = groupConnId} <- createMemberConnection_ db userId (groupMemberId' member) groupAgentConnId mcvr memberContactId cLevel currentTs subMode + liftIO $ setCommandConnId db user groupCmdId groupConnId + pure (member :: GroupMember) {activeConn = Just conn} createIntroToMemberContact :: DB.Connection -> User -> GroupMember -> GroupMember -> VersionRange -> (CommandId, ConnId) -> Maybe (CommandId, ConnId) -> Maybe ProfileId -> SubscriptionMode -> IO () createIntroToMemberContact db user@User {userId} GroupMember {memberContactId = viaContactId, activeConn} _to@GroupMember {groupMemberId, localDisplayName} mcvr (groupCmdId, groupAgentConnId) directConnIds customUserProfileId subMode = do - let cLevel = 1 + maybe 0 (connLevel :: Connection -> Int) activeConn + let cLevel = 1 + maybe 0 (\Connection {connLevel} -> connLevel) activeConn currentTs <- getCurrentTime Connection {connId = groupConnId} <- createMemberConnection_ db userId groupMemberId groupAgentConnId mcvr viaContactId cLevel currentTs subMode setCommandConnId db user groupCmdId groupConnId @@ -1209,14 +1276,16 @@ getViaGroupMember db vr User {userId, userContactId} Contact {contactId} = [sql| SELECT -- GroupInfo - g.group_id, g.local_display_name, gp.display_name, gp.full_name, gp.description, gp.image, g.host_conn_custom_user_profile_id, g.enable_ntfs, g.send_rcpts, g.favorite, gp.preferences, g.created_at, g.updated_at, g.chat_ts, + g.group_id, g.local_display_name, gp.display_name, gp.full_name, gp.description, gp.image, + g.host_conn_custom_user_profile_id, g.enable_ntfs, g.send_rcpts, g.favorite, gp.preferences, + g.created_at, g.updated_at, g.chat_ts, g.user_member_profile_sent_at, -- GroupInfo {membership} mu.group_member_id, mu.group_id, mu.member_id, mu.peer_chat_min_version, mu.peer_chat_max_version, mu.member_role, mu.member_category, - mu.member_status, mu.show_messages, mu.invited_by, mu.invited_by_group_member_id, mu.local_display_name, mu.contact_id, mu.contact_profile_id, pu.contact_profile_id, + mu.member_status, mu.show_messages, mu.member_restriction, mu.invited_by, mu.invited_by_group_member_id, mu.local_display_name, mu.contact_id, mu.contact_profile_id, pu.contact_profile_id, -- GroupInfo {membership = GroupMember {memberProfile}} pu.display_name, pu.full_name, pu.image, pu.contact_link, pu.local_alias, pu.preferences, -- via GroupMember - m.group_member_id, m.group_id, m.member_id, m.peer_chat_min_version, m.peer_chat_max_version, m.member_role, m.member_category, m.member_status, m.show_messages, + m.group_member_id, m.group_id, m.member_id, m.peer_chat_min_version, m.peer_chat_max_version, m.member_role, m.member_category, m.member_status, m.show_messages, m.member_restriction, m.invited_by, m.invited_by_group_member_id, m.local_display_name, m.contact_id, m.contact_profile_id, p.contact_profile_id, p.display_name, p.full_name, p.image, p.contact_link, p.local_alias, p.preferences, c.connection_id, c.agent_conn_id, c.conn_level, c.via_contact, c.via_user_contact_link, c.via_group_link, c.group_link_id, c.custom_user_profile_id, c.conn_status, c.conn_type, c.contact_conn_initiated, c.local_alias, c.contact_id, c.group_member_id, c.snd_file_id, c.rcv_file_id, c.user_contact_link_id, c.created_at, c.security_code, c.security_code_verified_at, c.auth_err_counter, @@ -1302,10 +1371,12 @@ getGroupInfo db vr User {userId, userContactId} groupId = [sql| SELECT -- GroupInfo - g.group_id, g.local_display_name, gp.display_name, gp.full_name, gp.description, gp.image, g.host_conn_custom_user_profile_id, g.enable_ntfs, g.send_rcpts, g.favorite, gp.preferences, g.created_at, g.updated_at, g.chat_ts, + g.group_id, g.local_display_name, gp.display_name, gp.full_name, gp.description, gp.image, + g.host_conn_custom_user_profile_id, g.enable_ntfs, g.send_rcpts, g.favorite, gp.preferences, + g.created_at, g.updated_at, g.chat_ts, g.user_member_profile_sent_at, -- GroupMember - membership mu.group_member_id, mu.group_id, mu.member_id, mu.peer_chat_min_version, mu.peer_chat_max_version, mu.member_role, mu.member_category, - mu.member_status, mu.show_messages, mu.invited_by, mu.invited_by_group_member_id, mu.local_display_name, mu.contact_id, mu.contact_profile_id, pu.contact_profile_id, + mu.member_status, mu.show_messages, mu.member_restriction, mu.invited_by, mu.invited_by_group_member_id, mu.local_display_name, mu.contact_id, mu.contact_profile_id, pu.contact_profile_id, pu.display_name, pu.full_name, pu.image, pu.contact_link, pu.local_alias, pu.preferences FROM groups g JOIN group_profiles gp ON gp.group_profile_id = g.group_profile_id @@ -1340,10 +1411,10 @@ getGroupInfoByGroupLinkHash db vr user@User {userId, userContactId} (groupLinkHa FROM groups g JOIN group_members mu ON mu.group_id = g.group_id WHERE g.user_id = ? AND g.via_group_link_uri_hash IN (?,?) - AND mu.contact_id = ? AND mu.member_status NOT IN (?,?,?) + AND mu.contact_id = ? AND mu.member_status NOT IN (?,?,?,?) LIMIT 1 |] - (userId, groupLinkHash1, groupLinkHash2, userContactId, GSMemRemoved, GSMemLeft, GSMemGroupDeleted) + (userId, groupLinkHash1, groupLinkHash2, userContactId, GSMemRemoved, GSMemLeft, GSMemGroupDeleted, GSMemUnknown) maybe (pure Nothing) (fmap eitherToMaybe . runExceptT . getGroupInfo db vr user) groupId_ getGroupIdByName :: DB.Connection -> User -> GroupName -> ExceptT StoreError IO GroupId @@ -1715,6 +1786,18 @@ updateGroupMemberSettings db User {userId} gId gMemberId GroupMemberSettings {sh |] (showMessages, currentTs, userId, gId, gMemberId) +updateGroupMemberBlocked :: DB.Connection -> User -> GroupId -> GroupMemberId -> MemberRestrictionStatus -> IO () +updateGroupMemberBlocked db User {userId} gId gMemberId memberBlocked = do + currentTs <- getCurrentTime + DB.execute + db + [sql| + UPDATE group_members + SET member_restriction = ?, updated_at = ? + WHERE user_id = ? AND group_id = ? AND group_member_id = ? + |] + (memberBlocked, currentTs, userId, gId, gMemberId) + getXGrpMemIntroContDirect :: DB.Connection -> User -> Contact -> IO (Maybe (Int64, XGrpMemIntroCont)) getXGrpMemIntroContDirect db User {userId} Contact {contactId} = do fmap join . maybeFirstRow toCont $ @@ -1937,12 +2020,12 @@ createMemberContactConn_ updateMemberProfile :: DB.Connection -> User -> GroupMember -> Profile -> ExceptT StoreError IO GroupMember updateMemberProfile db User {userId} m p' | displayName == newName = do - liftIO $ updateContactProfile_ db userId profileId p' + liftIO $ updateMemberContactProfileReset_ db userId profileId p' pure m {memberProfile = profile} | otherwise = ExceptT . withLocalDisplayName db userId newName $ \ldn -> do currentTs <- getCurrentTime - updateContactProfile_' db userId profileId p' currentTs + updateMemberContactProfileReset_' db userId profileId p' currentTs DB.execute db "UPDATE group_members SET local_display_name = ?, updated_at = ? WHERE user_id = ? AND group_member_id = ?" @@ -1954,6 +2037,22 @@ updateMemberProfile db User {userId} m p' Profile {displayName = newName} = p' profile = toLocalProfile profileId p' localAlias +updateContactMemberProfile :: DB.Connection -> User -> GroupMember -> Contact -> Profile -> ExceptT StoreError IO (GroupMember, Contact) +updateContactMemberProfile db User {userId} m ct@Contact {contactId} p' + | displayName == newName = do + liftIO $ updateMemberContactProfile_ db userId profileId p' + pure (m {memberProfile = profile}, ct {profile} :: Contact) + | otherwise = + ExceptT . withLocalDisplayName db userId newName $ \ldn -> do + currentTs <- getCurrentTime + updateMemberContactProfile_' db userId profileId p' currentTs + updateContactLDN_ db userId contactId localDisplayName ldn currentTs + pure $ Right (m {localDisplayName = ldn, memberProfile = profile}, ct {localDisplayName = ldn, profile} :: Contact) + where + GroupMember {localDisplayName, memberProfile = LocalProfile {profileId, displayName, localAlias}} = m + Profile {displayName = newName} = p' + profile = toLocalProfile profileId p' localAlias + getXGrpLinkMemReceived :: DB.Connection -> GroupMemberId -> ExceptT StoreError IO Bool getXGrpLinkMemReceived db mId = ExceptT . firstRow fromOnly (SEGroupMemberNotFound mId) $ @@ -1966,3 +2065,59 @@ setXGrpLinkMemReceived db mId xGrpLinkMemReceived = do db "UPDATE group_members SET xgrplinkmem_received = ?, updated_at = ? WHERE group_member_id = ?" (xGrpLinkMemReceived, currentTs, mId) + +createNewUnknownGroupMember :: DB.Connection -> VersionRange -> User -> GroupInfo -> MemberId -> Text -> ExceptT StoreError IO GroupMember +createNewUnknownGroupMember db vr user@User {userId, userContactId} GroupInfo {groupId} memberId memberName = do + currentTs <- liftIO getCurrentTime + let memberProfile = profileFromName memberName + (localDisplayName, profileId) <- createNewMemberProfile_ db user memberProfile currentTs + groupMemberId <- liftIO $ do + DB.execute + db + [sql| + INSERT INTO group_members + ( group_id, member_id, member_role, member_category, member_status, invited_by, + user_id, local_display_name, contact_id, contact_profile_id, created_at, updated_at, + peer_chat_min_version, peer_chat_max_version) + VALUES (?,?,?,?,?,?,?,?,?,?,?,?,?,?) + |] + ( (groupId, memberId, GRAuthor, GCPreMember, GSMemUnknown, fromInvitedBy userContactId IBUnknown) + :. (userId, localDisplayName, Nothing :: (Maybe Int64), profileId, currentTs, currentTs) + :. (minV, maxV) + ) + insertedRowId db + getGroupMemberById db user groupMemberId + where + VersionRange minV maxV = vr + +updateUnknownMemberAnnounced :: DB.Connection -> User -> GroupMember -> GroupMember -> MemberInfo -> ExceptT StoreError IO GroupMember +updateUnknownMemberAnnounced db user@User {userId} invitingMember unknownMember@GroupMember {groupMemberId, memberChatVRange} MemberInfo {memberRole, v, profile} = do + _ <- updateMemberProfile db user unknownMember profile + currentTs <- liftIO getCurrentTime + liftIO $ + DB.execute + db + [sql| + UPDATE group_members + SET member_role = ?, + member_category = ?, + member_status = ?, + invited_by_group_member_id = ?, + peer_chat_min_version = ?, + peer_chat_max_version = ?, + updated_at = ? + WHERE user_id = ? AND group_member_id = ? + |] + ( (memberRole, GCPostMember, GSMemAnnounced, groupMemberId' invitingMember) + :. (minV, maxV, currentTs, userId, groupMemberId) + ) + getGroupMemberById db user groupMemberId + where + VersionRange minV maxV = maybe (fromJVersionRange memberChatVRange) fromChatVRange v + +updateUserMemberProfileSentAt :: DB.Connection -> User -> GroupInfo -> UTCTime -> IO () +updateUserMemberProfileSentAt db User {userId} GroupInfo {groupId} sentTs = + DB.execute + db + "UPDATE groups SET user_member_profile_sent_at = ? WHERE user_id = ? AND group_id = ?" + (sentTs, userId, groupId) diff --git a/src/Simplex/Chat/Store/Messages.hs b/src/Simplex/Chat/Store/Messages.hs index fc840849ac..891e9887e6 100644 --- a/src/Simplex/Chat/Store/Messages.hs +++ b/src/Simplex/Chat/Store/Messages.hs @@ -34,9 +34,11 @@ module Simplex.Chat.Store.Messages createNewSndChatItem, createNewRcvChatItem, createNewChatItemNoMsg, + createNewChatItem_, getChatPreviews, getDirectChat, getGroupChat, + getLocalChat, getDirectChatItemsLast, getAllChatItems, getAChatItem, @@ -50,14 +52,18 @@ module Simplex.Chat.Store.Messages updateGroupChatItem, deleteGroupChatItem, updateGroupChatItemModerated, + updateGroupCIBlockedByAdmin, markGroupChatItemDeleted, markGroupChatItemBlocked, + markGroupCIBlockedByAdmin, + deleteLocalChatItem, updateDirectChatItemsRead, getDirectUnreadTimedItems, setDirectChatItemDeleteAt, updateGroupChatItemsRead, getGroupUnreadTimedItems, setGroupChatItemDeleteAt, + updateLocalChatItemsRead, getChatRefViaItemId, getChatItemVersions, getDirectCIReactions, @@ -77,10 +83,14 @@ module Simplex.Chat.Store.Messages getGroupMemberCIBySharedMsgId, getGroupChatItemByAgentMsgId, getGroupMemberChatItemLast, + getLocalChatItem, + updateLocalChatItem', getDirectChatItemIdByText, getDirectChatItemIdByText', getGroupChatItemIdByText, getGroupChatItemIdByText', + getLocalChatItemIdByText, + getLocalChatItemIdByText', getChatItemByFileId, getChatItemByGroupId, updateDirectChatItemStatus, @@ -126,6 +136,7 @@ import Simplex.Chat.Messages.CIContent import Simplex.Chat.Protocol import Simplex.Chat.Store.Direct import Simplex.Chat.Store.Groups +import Simplex.Chat.Store.NoteFolders import Simplex.Chat.Store.Shared import Simplex.Chat.Types import Simplex.Messaging.Agent.Protocol (AgentMsgId, ConnId, MsgMeta (..), UserId) @@ -322,6 +333,11 @@ updateChatTs db User {userId} chatDirection chatTs = case toChatInfo chatDirecti db "UPDATE groups SET chat_ts = ? WHERE user_id = ? AND group_id = ?" (chatTs, userId, groupId) + LocalChat NoteFolder {noteFolderId} -> + DB.execute + db + "UPDATE note_folders SET chat_ts = ? WHERE user_id = ? AND note_folder_id = ?" + (chatTs, userId, noteFolderId) _ -> pure () createNewSndChatItem :: DB.Connection -> User -> ChatDirection c 'MDSnd -> SndMessage -> CIContent 'MDSnd -> Maybe (CIQuote c) -> Maybe CITimed -> Bool -> UTCTime -> IO ChatItemId @@ -340,7 +356,7 @@ createNewSndChatItem db user chatDirection SndMessage {msgId, sharedMsgId} ciCon CIQGroupRcv (Just GroupMember {memberId}) -> (Just False, Just memberId) CIQGroupRcv Nothing -> (Just False, Nothing) -createNewRcvChatItem :: DB.Connection -> User -> ChatDirection c 'MDRcv -> RcvMessage -> Maybe SharedMsgId -> CIContent 'MDRcv -> Maybe CITimed -> Bool -> UTCTime -> UTCTime -> IO (ChatItemId, Maybe (CIQuote c)) +createNewRcvChatItem :: ChatTypeQuotable c => DB.Connection -> User -> ChatDirection c 'MDRcv -> RcvMessage -> Maybe SharedMsgId -> CIContent 'MDRcv -> Maybe CITimed -> Bool -> UTCTime -> UTCTime -> IO (ChatItemId, Maybe (CIQuote c)) createNewRcvChatItem db user chatDirection RcvMessage {msgId, chatMsgEvent, forwardedByMember} sharedMsgId_ ciContent timed live itemTs createdAt = do ciId <- createNewChatItem_ db user chatDirection (Just msgId) sharedMsgId_ ciContent quoteRow timed live itemTs forwardedByMember createdAt quotedItem <- mapM (getChatItemQuote_ db user chatDirection) quotedMsg @@ -370,13 +386,13 @@ createNewChatItem_ db User {userId} chatDirection msgId_ sharedMsgId ciContent q [sql| INSERT INTO chat_items ( -- user and IDs - user_id, created_by_msg_id, contact_id, group_id, group_member_id, + user_id, created_by_msg_id, contact_id, group_id, group_member_id, note_folder_id, -- meta item_sent, item_ts, item_content, item_content_tag, item_text, item_status, shared_msg_id, forwarded_by_group_member_id, created_at, updated_at, item_live, timed_ttl, timed_delete_at, -- quote quoted_shared_msg_id, quoted_sent_at, quoted_content, quoted_sent, quoted_member_id - ) VALUES (?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?) + ) VALUES (?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?) |] ((userId, msgId_) :. idsRow :. itemRow :. quoteRow) ciId <- insertedRowId db @@ -385,12 +401,14 @@ createNewChatItem_ db User {userId} chatDirection msgId_ sharedMsgId ciContent q where itemRow :: (SMsgDirection d, UTCTime, CIContent d, Text, Text, CIStatus d, Maybe SharedMsgId, Maybe GroupMemberId) :. (UTCTime, UTCTime, Maybe Bool) :. (Maybe Int, Maybe UTCTime) itemRow = (msgDirection @d, itemTs, ciContent, toCIContentTag ciContent, ciContentToText ciContent, ciCreateStatus ciContent, sharedMsgId, forwardedByMember) :. (createdAt, createdAt, justTrue live) :. ciTimedRow timed - idsRow :: (Maybe Int64, Maybe Int64, Maybe Int64) + idsRow :: (Maybe Int64, Maybe Int64, Maybe Int64, Maybe Int64) idsRow = case chatDirection of - CDDirectRcv Contact {contactId} -> (Just contactId, Nothing, Nothing) - CDDirectSnd Contact {contactId} -> (Just contactId, Nothing, Nothing) - CDGroupRcv GroupInfo {groupId} GroupMember {groupMemberId} -> (Nothing, Just groupId, Just groupMemberId) - CDGroupSnd GroupInfo {groupId} -> (Nothing, Just groupId, Nothing) + CDDirectRcv Contact {contactId} -> (Just contactId, Nothing, Nothing, Nothing) + CDDirectSnd Contact {contactId} -> (Just contactId, Nothing, Nothing, Nothing) + CDGroupRcv GroupInfo {groupId} GroupMember {groupMemberId} -> (Nothing, Just groupId, Just groupMemberId, Nothing) + CDGroupSnd GroupInfo {groupId} -> (Nothing, Just groupId, Nothing, Nothing) + CDLocalRcv NoteFolder {noteFolderId} -> (Nothing, Nothing, Nothing, Just noteFolderId) + CDLocalSnd NoteFolder {noteFolderId} -> (Nothing, Nothing, Nothing, Just noteFolderId) ciTimedRow :: Maybe CITimed -> (Maybe Int, Maybe UTCTime) ciTimedRow (Just CITimed {ttl, deleteAt}) = (Just ttl, deleteAt) @@ -399,7 +417,7 @@ ciTimedRow _ = (Nothing, Nothing) insertChatItemMessage_ :: DB.Connection -> ChatItemId -> MessageId -> UTCTime -> IO () insertChatItemMessage_ db ciId msgId ts = DB.execute db "INSERT INTO chat_item_messages (chat_item_id, message_id, created_at, updated_at) VALUES (?,?,?,?)" (ciId, msgId, ts, ts) -getChatItemQuote_ :: DB.Connection -> User -> ChatDirection c 'MDRcv -> QuotedMsg -> IO (CIQuote c) +getChatItemQuote_ :: ChatTypeQuotable c => DB.Connection -> User -> ChatDirection c 'MDRcv -> QuotedMsg -> IO (CIQuote c) getChatItemQuote_ db User {userId, userContactId} chatDirection QuotedMsg {msgRef = MsgRef {msgId, sentAt, sent, memberId}, content} = case chatDirection of CDDirectRcv Contact {contactId} -> getDirectChatItemQuote_ contactId (not sent) @@ -446,7 +464,7 @@ getChatItemQuote_ db User {userId, userContactId} chatDirection QuotedMsg {msgRe SELECT i.chat_item_id, -- GroupMember m.group_member_id, m.group_id, m.member_id, m.peer_chat_min_version, m.peer_chat_max_version, m.member_role, m.member_category, - m.member_status, m.show_messages, m.invited_by, m.invited_by_group_member_id, m.local_display_name, m.contact_id, m.contact_profile_id, p.contact_profile_id, + m.member_status, m.show_messages, m.member_restriction, m.invited_by, m.invited_by_group_member_id, m.local_display_name, m.contact_id, m.contact_profile_id, p.contact_profile_id, p.display_name, p.full_name, p.image, p.contact_link, p.local_alias, p.preferences FROM group_members m JOIN contact_profiles p ON p.contact_profile_id = COALESCE(m.member_profile_id, m.contact_profile_id) @@ -466,15 +484,17 @@ getChatPreviews :: DB.Connection -> VersionRange -> User -> Bool -> PaginationBy getChatPreviews db vr user withPCC pagination query = do directChats <- findDirectChatPreviews_ db user pagination query groupChats <- findGroupChatPreviews_ db user pagination query + localChats <- findLocalChatPreviews_ db user pagination query cReqChats <- getContactRequestChatPreviews_ db user pagination query connChats <- if withPCC then getContactConnectionChatPreviews_ db user pagination query else pure [] - let refs = sortTake $ concat [directChats, groupChats, cReqChats, connChats] + let refs = sortTake $ concat [directChats, groupChats, localChats, cReqChats, connChats] mapM (runExceptT <$> getChatPreview) refs where ts :: AChatPreviewData -> UTCTime ts (ACPD _ cpd) = case cpd of (DirectChatPD t _ _ _) -> t (GroupChatPD t _ _ _) -> t + (LocalChatPD t _ _ _) -> t (ContactRequestPD t _) -> t (ContactConnectionPD t _) -> t sortTake = case pagination of @@ -485,12 +505,14 @@ getChatPreviews db vr user withPCC pagination query = do getChatPreview (ACPD cType cpd) = case cType of SCTDirect -> getDirectChatPreview_ db user cpd SCTGroup -> getGroupChatPreview_ db vr user cpd + SCTLocal -> getLocalChatPreview_ db user cpd SCTContactRequest -> let (ContactRequestPD _ chat) = cpd in pure chat SCTContactConnection -> let (ContactConnectionPD _ chat) = cpd in pure chat data ChatPreviewData (c :: ChatType) where DirectChatPD :: UTCTime -> ContactId -> Maybe ChatItemId -> ChatStats -> ChatPreviewData 'CTDirect GroupChatPD :: UTCTime -> GroupId -> Maybe ChatItemId -> ChatStats -> ChatPreviewData 'CTGroup + LocalChatPD :: UTCTime -> NoteFolderId -> Maybe ChatItemId -> ChatStats -> ChatPreviewData 'CTLocal ContactRequestPD :: UTCTime -> AChat -> ChatPreviewData 'CTContactRequest ContactConnectionPD :: UTCTime -> AChat -> ChatPreviewData 'CTContactConnection @@ -521,12 +543,13 @@ findDirectChatPreviews_ db User {userId} pagination clq = LEFT JOIN ( SELECT contact_id, chat_item_id, MAX(created_at) FROM chat_items + WHERE user_id = :user_id AND contact_id IS NOT NULL GROUP BY contact_id ) LastItems ON LastItems.contact_id = ct.contact_id LEFT JOIN ( SELECT contact_id, COUNT(1) AS UnreadCount, MIN(chat_item_id) AS MinUnread FROM chat_items - WHERE item_status = :rcv_new + WHERE user_id = :user_id AND contact_id IS NOT NULL AND item_status = :rcv_new GROUP BY contact_id ) ChatStats ON ChatStats.contact_id = ct.contact_id |] @@ -616,12 +639,13 @@ findGroupChatPreviews_ db User {userId} pagination clq = LEFT JOIN ( SELECT group_id, chat_item_id, MAX(item_ts) FROM chat_items + WHERE user_id = :user_id AND group_id IS NOT NULL GROUP BY group_id ) LastItems ON LastItems.group_id = g.group_id LEFT JOIN ( SELECT group_id, COUNT(1) AS UnreadCount, MIN(chat_item_id) AS MinUnread FROM chat_items - WHERE item_status = :rcv_new + WHERE user_id = :user_id AND group_id IS NOT NULL AND item_status = :rcv_new GROUP BY group_id ) ChatStats ON ChatStats.group_id = g.group_id |] @@ -697,6 +721,124 @@ getGroupChatPreview_ db vr user (GroupChatPD _ groupId lastItemId_ stats) = do Nothing -> pure [] pure $ AChat SCTGroup (Chat (GroupChat groupInfo) lastItem stats) +findLocalChatPreviews_ :: DB.Connection -> User -> PaginationByTime -> ChatListQuery -> IO [AChatPreviewData] +findLocalChatPreviews_ db User {userId} pagination clq = + map toPreview <$> getPreviews + where + toPreview :: (NoteFolderId, UTCTime, Maybe ChatItemId) :. ChatStatsRow -> AChatPreviewData + toPreview ((noteFolderId, ts, lastItemId_) :. statsRow) = + ACPD SCTLocal $ LocalChatPD ts noteFolderId lastItemId_ (toChatStats statsRow) + baseQuery = + [sql| + SELECT nf.note_folder_id, nf.chat_ts as ts, LastItems.chat_item_id, COALESCE(ChatStats.UnreadCount, 0), COALESCE(ChatStats.MinUnread, 0), nf.unread_chat + FROM note_folders nf + LEFT JOIN ( + SELECT note_folder_id, chat_item_id, MAX(created_at) + FROM chat_items + WHERE user_id = :user_id AND note_folder_id IS NOT NULL + GROUP BY note_folder_id + ) LastItems ON LastItems.note_folder_id = nf.note_folder_id + LEFT JOIN ( + SELECT note_folder_id, COUNT(1) AS UnreadCount, MIN(chat_item_id) AS MinUnread + FROM chat_items + WHERE user_id = :user_id AND note_folder_id IS NOT NULL AND item_status = :rcv_new + GROUP BY note_folder_id + ) ChatStats ON ChatStats.note_folder_id = nf.note_folder_id + |] + (pagQuery, pagParams) = paginationByTimeFilter pagination + getPreviews = case clq of + CLQFilters {favorite = False, unread = False} -> + DB.queryNamed + db + ( baseQuery + <> [sql| + WHERE nf.user_id = :user_id + |] + <> pagQuery + ) + ([":user_id" := userId, ":rcv_new" := CISRcvNew] <> pagParams) + CLQFilters {favorite = True, unread = False} -> + DB.queryNamed + db + ( baseQuery + <> [sql| + WHERE nf.user_id = :user_id + AND nf.favorite = 1 + |] + <> pagQuery + ) + ([":user_id" := userId, ":rcv_new" := CISRcvNew] <> pagParams) + CLQFilters {favorite = False, unread = True} -> + DB.queryNamed + db + ( baseQuery + <> [sql| + WHERE nf.user_id = :user_id + AND (nf.unread_chat = 1 OR ChatStats.UnreadCount > 0) + |] + <> pagQuery + ) + ([":user_id" := userId, ":rcv_new" := CISRcvNew] <> pagParams) + CLQFilters {favorite = True, unread = True} -> + DB.queryNamed + db + ( baseQuery + <> [sql| + WHERE nf.user_id = :user_id + AND (nf.favorite = 1 + OR nf.unread_chat = 1 OR ChatStats.UnreadCount > 0) + |] + <> pagQuery + ) + ([":user_id" := userId, ":rcv_new" := CISRcvNew] <> pagParams) + CLQSearch {} -> pure [] + +getLocalChatPreview_ :: DB.Connection -> User -> ChatPreviewData 'CTLocal -> ExceptT StoreError IO AChat +getLocalChatPreview_ db user (LocalChatPD _ noteFolderId lastItemId_ stats) = do + nf <- getNoteFolder db user noteFolderId + lastItem <- case lastItemId_ of + Just lastItemId -> (: []) <$> getLocalChatItem db user noteFolderId lastItemId + Nothing -> pure [] + pure $ AChat SCTLocal (Chat (LocalChat nf) lastItem stats) + +-- this function can be changed so it never fails, not only avoid failure on invalid json +toLocalChatItem :: UTCTime -> ChatItemRow -> Either StoreError (CChatItem 'CTLocal) +toLocalChatItem currentTs ((itemId, itemTs, AMsgDirection msgDir, itemContentText, itemText, itemStatus, sharedMsgId) :. (itemDeleted, deletedTs, itemEdited, createdAt, updatedAt) :. (timedTTL, timedDeleteAt, itemLive) :. (fileId_, fileName_, fileSize_, filePath, fileKey, fileNonce, fileStatus_, fileProtocol_)) = + chatItem $ fromRight invalid $ dbParseACIContent itemContentText + where + invalid = ACIContent msgDir $ CIInvalidJSON itemContentText + chatItem itemContent = case (itemContent, itemStatus, fileStatus_) of + (ACIContent SMDSnd ciContent, ACIStatus SMDSnd ciStatus, Just (AFS SMDSnd fileStatus)) -> + Right $ cItem SMDSnd CILocalSnd ciStatus ciContent (maybeCIFile fileStatus) + (ACIContent SMDSnd ciContent, ACIStatus SMDSnd ciStatus, Nothing) -> + Right $ cItem SMDSnd CILocalSnd ciStatus ciContent Nothing + (ACIContent SMDRcv ciContent, ACIStatus SMDRcv ciStatus, Just (AFS SMDRcv fileStatus)) -> + Right $ cItem SMDRcv CILocalRcv ciStatus ciContent (maybeCIFile fileStatus) + (ACIContent SMDRcv ciContent, ACIStatus SMDRcv ciStatus, Nothing) -> + Right $ cItem SMDRcv CILocalRcv ciStatus ciContent Nothing + _ -> badItem + maybeCIFile :: CIFileStatus d -> Maybe (CIFile d) + maybeCIFile fileStatus = + case (fileId_, fileName_, fileSize_, fileProtocol_) of + (Just fileId, Just fileName, Just fileSize, Just fileProtocol) -> + let cfArgs = CFArgs <$> fileKey <*> fileNonce + fileSource = (`CryptoFile` cfArgs) <$> filePath + in Just CIFile {fileId, fileName, fileSize, fileSource, fileStatus, fileProtocol} + _ -> Nothing + cItem :: MsgDirectionI d => SMsgDirection d -> CIDirection 'CTLocal d -> CIStatus d -> CIContent d -> Maybe (CIFile d) -> CChatItem 'CTLocal + cItem d chatDir ciStatus content file = + CChatItem d ChatItem {chatDir, meta = ciMeta content ciStatus, content, formattedText = parseMaybeMarkdownList itemText, quotedItem = Nothing, reactions = [], file} + badItem = Left $ SEBadChatItem itemId + ciMeta :: CIContent d -> CIStatus d -> CIMeta 'CTLocal d + ciMeta content status = + let itemDeleted' = case itemDeleted of + DBCINotDeleted -> Nothing + _ -> Just (CIDeleted @CTLocal deletedTs) + itemEdited' = fromMaybe False itemEdited + in mkCIMeta itemId content itemText status sharedMsgId itemDeleted' itemEdited' ciTimed itemLive currentTs itemTs Nothing createdAt updatedAt + ciTimed :: Maybe CITimed + ciTimed = timedTTL >>= \ttl -> Just CITimed {ttl, deleteAt = timedDeleteAt} + getContactRequestChatPreviews_ :: DB.Connection -> User -> PaginationByTime -> ChatListQuery -> IO [AChatPreviewData] getContactRequestChatPreviews_ db User {userId} pagination clq = case clq of CLQFilters {favorite = False, unread = False} -> query "" @@ -967,11 +1109,86 @@ getGroupChatBefore_ db user@User {userId} g@GroupInfo {groupId} beforeChatItemId |] (userId, groupId, search, beforeChatItemTs, beforeChatItemTs, beforeChatItemId, count) -toChatItemRef :: (ChatItemId, Maybe Int64, Maybe Int64) -> Either StoreError (ChatRef, ChatItemId) +getLocalChat :: DB.Connection -> User -> Int64 -> ChatPagination -> Maybe String -> ExceptT StoreError IO (Chat 'CTLocal) +getLocalChat db user folderId pagination search_ = do + let search = fromMaybe "" search_ + nf <- getNoteFolder db user folderId + case pagination of + CPLast count -> getLocalChatLast_ db user nf count search + CPAfter afterId count -> getLocalChatAfter_ db user nf afterId count search + CPBefore beforeId count -> getLocalChatBefore_ db user nf beforeId count search + +getLocalChatLast_ :: DB.Connection -> User -> NoteFolder -> Int -> String -> ExceptT StoreError IO (Chat 'CTLocal) +getLocalChatLast_ db user@User {userId} nf@NoteFolder {noteFolderId} count search = do + let stats = ChatStats {unreadCount = 0, minUnreadItemId = 0, unreadChat = False} + chatItemIds <- liftIO getLocalChatItemIdsLast_ + chatItems <- mapM (getLocalChatItem db user noteFolderId) chatItemIds + pure $ Chat (LocalChat nf) (reverse chatItems) stats + where + getLocalChatItemIdsLast_ :: IO [ChatItemId] + getLocalChatItemIdsLast_ = + map fromOnly + <$> DB.query + db + [sql| + SELECT chat_item_id + FROM chat_items + WHERE user_id = ? AND note_folder_id = ? AND item_text LIKE '%' || ? || '%' + ORDER BY created_at DESC, chat_item_id DESC + LIMIT ? + |] + (userId, noteFolderId, search, count) + +getLocalChatAfter_ :: DB.Connection -> User -> NoteFolder -> ChatItemId -> Int -> String -> ExceptT StoreError IO (Chat 'CTLocal) +getLocalChatAfter_ db user@User {userId} nf@NoteFolder {noteFolderId} afterChatItemId count search = do + let stats = ChatStats {unreadCount = 0, minUnreadItemId = 0, unreadChat = False} + chatItemIds <- liftIO getLocalChatItemIdsAfter_ + chatItems <- mapM (getLocalChatItem db user noteFolderId) chatItemIds + pure $ Chat (LocalChat nf) chatItems stats + where + getLocalChatItemIdsAfter_ :: IO [ChatItemId] + getLocalChatItemIdsAfter_ = + map fromOnly + <$> DB.query + db + [sql| + SELECT chat_item_id + FROM chat_items + WHERE user_id = ? AND note_folder_id = ? AND item_text LIKE '%' || ? || '%' + AND chat_item_id > ? + ORDER BY created_at ASC, chat_item_id ASC + LIMIT ? + |] + (userId, noteFolderId, search, afterChatItemId, count) + +getLocalChatBefore_ :: DB.Connection -> User -> NoteFolder -> ChatItemId -> Int -> String -> ExceptT StoreError IO (Chat 'CTLocal) +getLocalChatBefore_ db user@User {userId} nf@NoteFolder {noteFolderId} beforeChatItemId count search = do + let stats = ChatStats {unreadCount = 0, minUnreadItemId = 0, unreadChat = False} + chatItemIds <- liftIO getLocalChatItemIdsBefore_ + chatItems <- mapM (getLocalChatItem db user noteFolderId) chatItemIds + pure $ Chat (LocalChat nf) (reverse chatItems) stats + where + getLocalChatItemIdsBefore_ :: IO [ChatItemId] + getLocalChatItemIdsBefore_ = + map fromOnly + <$> DB.query + db + [sql| + SELECT chat_item_id + FROM chat_items + WHERE user_id = ? AND note_folder_id = ? AND item_text LIKE '%' || ? || '%' + AND chat_item_id < ? + ORDER BY created_at DESC, chat_item_id DESC + LIMIT ? + |] + (userId, noteFolderId, search, beforeChatItemId, count) + +toChatItemRef :: (ChatItemId, Maybe Int64, Maybe Int64, Maybe Int64) -> Either StoreError (ChatRef, ChatItemId) toChatItemRef = \case - (itemId, Just contactId, Nothing) -> Right (ChatRef CTDirect contactId, itemId) - (itemId, Nothing, Just groupId) -> Right (ChatRef CTGroup groupId, itemId) - (itemId, _, _) -> Left $ SEBadChatItem itemId + (itemId, Just contactId, Nothing, Nothing) -> Right (ChatRef CTDirect contactId, itemId) + (itemId, Nothing, Just groupId, Nothing) -> Right (ChatRef CTGroup groupId, itemId) + (itemId, Nothing, Nothing, Just folderId) -> Right (ChatRef CTLocal folderId, itemId) + (itemId, _, _, _) -> Left $ SEBadChatItem itemId updateDirectChatItemsRead :: DB.Connection -> User -> ContactId -> Maybe (ChatItemId, ChatItemId) -> IO () updateDirectChatItemsRead db User {userId} contactId itemsRange_ = do @@ -1079,6 +1296,27 @@ setGroupChatItemDeleteAt db User {userId} groupId chatItemId deleteAt = "UPDATE chat_items SET timed_delete_at = ? WHERE user_id = ? AND group_id = ? AND chat_item_id = ?" (deleteAt, userId, groupId, chatItemId) +updateLocalChatItemsRead :: DB.Connection -> User -> NoteFolderId -> Maybe (ChatItemId, ChatItemId) -> IO () +updateLocalChatItemsRead db User {userId} noteFolderId itemsRange_ = do + currentTs <- getCurrentTime + case itemsRange_ of + Just (fromItemId, toItemId) -> + DB.execute + db + [sql| + UPDATE chat_items SET item_status = ?, updated_at = ? + WHERE user_id = ? AND note_folder_id = ? AND chat_item_id >= ? AND chat_item_id <= ? AND item_status = ? + |] + (CISRcvRead, currentTs, userId, noteFolderId, fromItemId, toItemId, CISRcvNew) + _ -> + DB.execute + db + [sql| + UPDATE chat_items SET item_status = ?, updated_at = ? + WHERE user_id = ? AND note_folder_id = ? AND item_status = ? + |] + (CISRcvRead, currentTs, userId, noteFolderId, CISRcvNew) + type MaybeCIFIleRow = (Maybe Int64, Maybe String, Maybe Integer, Maybe FilePath, Maybe C.SbKey, Maybe C.CbNonce, Maybe ACIFileStatus, Maybe FileProtocol) type ChatItemModeRow = (Maybe Int, Maybe UTCTime, Maybe Bool) @@ -1128,7 +1366,7 @@ toDirectChatItem currentTs (((itemId, itemTs, AMsgDirection msgDir, itemContentT ciMeta content status = let itemDeleted' = case itemDeleted of DBCINotDeleted -> Nothing - _ -> Just (CIDeleted @'CTDirect deletedTs) + _ -> Just (CIDeleted @CTDirect deletedTs) itemEdited' = fromMaybe False itemEdited in mkCIMeta itemId content itemText status sharedMsgId itemDeleted' itemEdited' ciTimed itemLive currentTs itemTs Nothing createdAt updatedAt ciTimed :: Maybe CITimed @@ -1180,7 +1418,8 @@ toGroupChatItem currentTs userContactId (((itemId, itemTs, AMsgDirection msgDir, let itemDeleted' = case itemDeleted of DBCINotDeleted -> Nothing DBCIBlocked -> Just (CIBlocked deletedTs) - _ -> Just (maybe (CIDeleted @'CTGroup deletedTs) (CIModerated deletedTs) deletedByGroupMember_) + DBCIBlockedByAdmin -> Just (CIBlockedByAdmin deletedTs) + _ -> Just (maybe (CIDeleted @CTGroup deletedTs) (CIModerated deletedTs) deletedByGroupMember_) itemEdited' = fromMaybe False itemEdited in mkCIMeta itemId content itemText status sharedMsgId itemDeleted' itemEdited' ciTimed itemLive currentTs itemTs forwardedByMember createdAt updatedAt ciTimed :: Maybe CITimed @@ -1204,7 +1443,7 @@ getAllChatItems db vr user@User {userId} pagination search_ = do <$> DB.query db [sql| - SELECT chat_item_id, contact_id, group_id + SELECT chat_item_id, contact_id, group_id, note_folder_id FROM chat_items WHERE user_id = ? AND item_text LIKE '%' || ? || '%' ORDER BY item_ts DESC, chat_item_id DESC @@ -1215,7 +1454,7 @@ getAllChatItems db vr user@User {userId} pagination search_ = do DB.query db [sql| - SELECT chat_item_id, contact_id, group_id + SELECT chat_item_id, contact_id, group_id, note_folder_id FROM chat_items WHERE user_id = ? AND item_text LIKE '%' || ? || '%' AND (item_ts > ? OR (item_ts = ? AND chat_item_id > ?)) @@ -1228,7 +1467,7 @@ getAllChatItems db vr user@User {userId} pagination search_ = do <$> DB.query db [sql| - SELECT chat_item_id, contact_id, group_id + SELECT chat_item_id, contact_id, group_id, note_folder_id FROM chat_items WHERE user_id = ? AND item_text LIKE '%' || ? || '%' AND (item_ts < ? OR (item_ts = ? AND chat_item_id < ?)) @@ -1531,7 +1770,24 @@ updateGroupChatItemModerated db User {userId} GroupInfo {groupId} ci m@GroupMemb WHERE user_id = ? AND group_id = ? AND chat_item_id = ? |] (deletedTs, groupMemberId, toContent, toText, currentTs, userId, groupId, itemId) - pure $ ci {content = toContent, meta = (meta ci) {itemText = toText, itemDeleted = Just (CIModerated (Just currentTs) m), editable = False}, formattedText = Nothing} + pure $ ci {content = toContent, meta = (meta ci) {itemText = toText, itemDeleted = Just (CIModerated (Just deletedTs) m), editable = False}, formattedText = Nothing} + +updateGroupCIBlockedByAdmin :: DB.Connection -> User -> GroupInfo -> ChatItem 'CTGroup d -> UTCTime -> IO (ChatItem 'CTGroup d) +updateGroupCIBlockedByAdmin db User {userId} GroupInfo {groupId} ci deletedTs = do + currentTs <- getCurrentTime + let itemId = chatItemId' ci + deleteChatItemMessages_ db itemId + deleteChatItemVersions_ db itemId + liftIO $ + DB.execute + db + [sql| + UPDATE chat_items + SET item_deleted = ?, item_deleted_ts = ?, updated_at = ? + WHERE user_id = ? AND group_id = ? AND chat_item_id = ? + |] + (DBCIBlockedByAdmin, deletedTs, currentTs, userId, groupId, itemId) + pure $ ci {meta = (meta ci) {itemDeleted = Just (CIBlockedByAdmin $ Just deletedTs), editable = False}, formattedText = Nothing} pattern DBCINotDeleted :: Int pattern DBCINotDeleted = 0 @@ -1542,13 +1798,16 @@ pattern DBCIDeleted = 1 pattern DBCIBlocked :: Int pattern DBCIBlocked = 2 +pattern DBCIBlockedByAdmin :: Int +pattern DBCIBlockedByAdmin = 3 + markGroupChatItemDeleted :: DB.Connection -> User -> GroupInfo -> ChatItem 'CTGroup d -> MessageId -> Maybe GroupMember -> UTCTime -> IO (ChatItem 'CTGroup d) markGroupChatItemDeleted db User {userId} GroupInfo {groupId} ci@ChatItem {meta} msgId byGroupMember_ deletedTs = do currentTs <- liftIO getCurrentTime let itemId = chatItemId' ci (deletedByGroupMemberId, itemDeleted) = case byGroupMember_ of Just m@GroupMember {groupMemberId} -> (Just groupMemberId, Just $ CIModerated (Just deletedTs) m) - _ -> (Nothing, Just $ CIDeleted @'CTGroup (Just deletedTs)) + _ -> (Nothing, Just $ CIDeleted @CTGroup (Just deletedTs)) insertChatItemMessage_ db itemId msgId currentTs DB.execute db @@ -1573,6 +1832,19 @@ markGroupChatItemBlocked db User {userId} GroupInfo {groupId} ci@ChatItem {meta} (DBCIBlocked, deletedTs, deletedTs, userId, groupId, chatItemId' ci) pure ci {meta = meta {itemDeleted = Just $ CIBlocked $ Just deletedTs}} +markGroupCIBlockedByAdmin :: DB.Connection -> User -> GroupInfo -> ChatItem 'CTGroup 'MDRcv -> IO (ChatItem 'CTGroup 'MDRcv) +markGroupCIBlockedByAdmin db User {userId} GroupInfo {groupId} ci@ChatItem {meta} = do + deletedTs <- getCurrentTime + DB.execute + db + [sql| + UPDATE chat_items + SET item_deleted = ?, item_deleted_ts = ?, updated_at = ? + WHERE user_id = ? AND group_id = ? AND chat_item_id = ? + |] + (DBCIBlockedByAdmin, deletedTs, deletedTs, userId, groupId, chatItemId' ci) + pure ci {meta = meta {itemDeleted = Just $ CIBlockedByAdmin $ Just deletedTs}} + getGroupChatItemBySharedMsgId :: DB.Connection -> User -> GroupId -> GroupMemberId -> SharedMsgId -> ExceptT StoreError IO (CChatItem 'CTGroup) getGroupChatItemBySharedMsgId db user@User {userId} groupId groupMemberId sharedMsgId = do itemId <- @@ -1631,17 +1903,17 @@ getGroupChatItem db User {userId, userContactId} groupId itemId = ExceptT $ do i.forwarded_by_group_member_id, -- GroupMember m.group_member_id, m.group_id, m.member_id, m.peer_chat_min_version, m.peer_chat_max_version, m.member_role, m.member_category, - m.member_status, m.show_messages, m.invited_by, m.invited_by_group_member_id, m.local_display_name, m.contact_id, m.contact_profile_id, p.contact_profile_id, + m.member_status, m.show_messages, m.member_restriction, m.invited_by, m.invited_by_group_member_id, m.local_display_name, m.contact_id, m.contact_profile_id, p.contact_profile_id, p.display_name, p.full_name, p.image, p.contact_link, p.local_alias, p.preferences, -- quoted ChatItem ri.chat_item_id, i.quoted_shared_msg_id, i.quoted_sent_at, i.quoted_content, i.quoted_sent, -- quoted GroupMember rm.group_member_id, rm.group_id, rm.member_id, rm.peer_chat_min_version, rm.peer_chat_max_version, rm.member_role, rm.member_category, - rm.member_status, rm.show_messages, rm.invited_by, rm.invited_by_group_member_id, rm.local_display_name, rm.contact_id, rm.contact_profile_id, rp.contact_profile_id, + rm.member_status, rm.show_messages, rm.member_restriction, rm.invited_by, rm.invited_by_group_member_id, rm.local_display_name, rm.contact_id, rm.contact_profile_id, rp.contact_profile_id, rp.display_name, rp.full_name, rp.image, rp.contact_link, rp.local_alias, rp.preferences, -- deleted by GroupMember dbm.group_member_id, dbm.group_id, dbm.member_id, dbm.peer_chat_min_version, dbm.peer_chat_max_version, dbm.member_role, dbm.member_category, - dbm.member_status, dbm.show_messages, dbm.invited_by, dbm.invited_by_group_member_id, dbm.local_display_name, dbm.contact_id, dbm.contact_profile_id, dbp.contact_profile_id, + dbm.member_status, dbm.show_messages, dbm.member_restriction, dbm.invited_by, dbm.invited_by_group_member_id, dbm.local_display_name, dbm.contact_id, dbm.contact_profile_id, dbp.contact_profile_id, dbp.display_name, dbp.full_name, dbp.image, dbp.contact_link, dbp.local_alias, dbp.preferences FROM chat_items i LEFT JOIN files f ON f.chat_item_id = i.chat_item_id @@ -1714,6 +1986,89 @@ getGroupChatItemIdByText' db User {userId} groupId msg = |] (userId, groupId, msg <> "%") +getLocalChatItem :: DB.Connection -> User -> Int64 -> ChatItemId -> ExceptT StoreError IO (CChatItem 'CTLocal) +getLocalChatItem db User {userId} folderId itemId = ExceptT $ do + currentTs <- getCurrentTime + firstRow' (toLocalChatItem currentTs) (SEChatItemNotFound itemId) getItem + where + getItem = + DB.query + db + [sql| + SELECT + -- ChatItem + i.chat_item_id, i.item_ts, i.item_sent, i.item_content, i.item_text, i.item_status, i.shared_msg_id, i.item_deleted, i.item_deleted_ts, i.item_edited, i.created_at, i.updated_at, i.timed_ttl, i.timed_delete_at, i.item_live, + -- CIFile + f.file_id, f.file_name, f.file_size, f.file_path, f.file_crypto_key, f.file_crypto_nonce, f.ci_file_status, f.protocol + FROM chat_items i + LEFT JOIN files f ON f.chat_item_id = i.chat_item_id + WHERE i.user_id = ? AND i.note_folder_id = ? AND i.chat_item_id = ? + |] + (userId, folderId, itemId) + +getLocalChatItemIdByText :: DB.Connection -> User -> NoteFolderId -> SMsgDirection d -> Text -> ExceptT StoreError IO ChatItemId +getLocalChatItemIdByText db User {userId} noteFolderId msgDir quotedMsg = + ExceptT . firstRow fromOnly (SEChatItemNotFoundByText quotedMsg) $ + DB.query + db + [sql| + SELECT chat_item_id + FROM chat_items + WHERE user_id = ? AND note_folder_id = ? AND item_sent = ? AND item_text LIKE ? + ORDER BY chat_item_id DESC + LIMIT 1 + |] + (userId, noteFolderId, msgDir, quotedMsg <> "%") + +getLocalChatItemIdByText' :: DB.Connection -> User -> NoteFolderId -> Text -> ExceptT StoreError IO ChatItemId +getLocalChatItemIdByText' db User {userId} noteFolderId msg = + ExceptT . firstRow fromOnly (SEChatItemNotFoundByText msg) $ + DB.query + db + [sql| + SELECT chat_item_id + FROM chat_items + WHERE user_id = ? AND note_folder_id = ? AND item_text LIKE ? + ORDER BY chat_item_id DESC + LIMIT 1 + |] + (userId, noteFolderId, msg <> "%") + +updateLocalChatItem' :: forall d. MsgDirectionI d => DB.Connection -> User -> NoteFolderId -> ChatItem 'CTLocal d -> CIContent d -> IO (ChatItem 'CTLocal d) +updateLocalChatItem' db User {userId} noteFolderId ci newContent = do + currentTs <- liftIO getCurrentTime + let ci' = updatedChatItem ci newContent False currentTs + liftIO $ updateLocalChatItem_ db userId noteFolderId ci' + pure ci' + +-- this function assumes that local item with correct chat direction already exists, +-- it should be checked before calling it +updateLocalChatItem_ :: forall d. MsgDirectionI d => DB.Connection -> UserId -> NoteFolderId -> ChatItem 'CTLocal d -> IO () +updateLocalChatItem_ db userId noteFolderId ChatItem {meta, content} = do + let CIMeta {itemId, itemText, itemStatus, itemDeleted, itemEdited, updatedAt} = meta + itemDeleted' = isJust itemDeleted + itemDeletedTs' = itemDeletedTs =<< itemDeleted + DB.execute + db + [sql| + UPDATE chat_items + SET item_content = ?, item_text = ?, item_status = ?, item_deleted = ?, item_deleted_ts = ?, item_edited = ?, updated_at = ? + WHERE user_id = ? AND note_folder_id = ? AND chat_item_id = ? + |] + ((content, itemText, itemStatus, itemDeleted', itemDeletedTs', itemEdited, updatedAt) :. (userId, noteFolderId, itemId)) + +deleteLocalChatItem :: DB.Connection -> User -> NoteFolder -> ChatItem 'CTLocal d -> IO () +deleteLocalChatItem db User {userId} NoteFolder {noteFolderId} ci = do + let itemId = chatItemId' ci + deleteChatItemVersions_ db itemId + DB.execute + db + [sql| + DELETE FROM chat_items + WHERE user_id = ? AND note_folder_id = ? AND chat_item_id = ? + |] + (userId, noteFolderId, itemId) + getChatItemByFileId :: DB.Connection -> VersionRange -> User -> Int64 -> ExceptT StoreError IO AChatItem getChatItemByFileId db vr user@User {userId} fileId = do (chatRef, itemId) <- @@ -1721,7 +2076,7 @@ getChatItemByFileId db vr user@User {userId} fileId = do DB.query db [sql| - SELECT i.chat_item_id, i.contact_id, i.group_id + SELECT i.chat_item_id, i.contact_id, i.group_id, i.note_folder_id FROM chat_items i JOIN files f ON f.chat_item_id = i.chat_item_id WHERE f.user_id = ? AND f.file_id = ? @@ -1737,7 +2092,7 @@ getChatItemByGroupId db vr user@User {userId} groupId = do DB.query db [sql| - SELECT i.chat_item_id, i.contact_id, i.group_id + SELECT i.chat_item_id, i.contact_id, i.group_id, i.note_folder_id FROM chat_items i JOIN groups g ON g.chat_item_id = i.chat_item_id WHERE g.user_id = ? AND g.group_id = ? @@ -1766,6 +2121,10 @@ getAChatItem db vr user chatRef itemId = case chatRef of gInfo <- getGroupInfo db vr user groupId (CChatItem msgDir ci) <- getGroupChatItem db user groupId itemId pure $ AChatItem SCTGroup msgDir (GroupChat gInfo) ci + ChatRef CTLocal folderId -> do + nf <- getNoteFolder db user folderId + CChatItem msgDir ci <- getLocalChatItem db user folderId itemId + pure $ AChatItem SCTLocal msgDir (LocalChat nf) ci _ -> throwError $ SEChatItemNotFound itemId getChatItemVersions :: DB.Connection -> ChatItemId -> IO [ChatItemVersion] diff --git a/src/Simplex/Chat/Store/Migrations.hs b/src/Simplex/Chat/Store/Migrations.hs index 61fbfe3598..2f5e61a5e6 100644 --- a/src/Simplex/Chat/Store/Migrations.hs +++ b/src/Simplex/Chat/Store/Migrations.hs @@ -94,6 +94,10 @@ import Simplex.Chat.Migrations.M20231126_remote_ctrl_address import Simplex.Chat.Migrations.M20231207_chat_list_pagination import Simplex.Chat.Migrations.M20231214_item_content_tag import Simplex.Chat.Migrations.M20231215_recreate_msg_deliveries +import Simplex.Chat.Migrations.M20240102_note_folders +import Simplex.Chat.Migrations.M20240104_members_profile_update +import Simplex.Chat.Migrations.M20240115_block_member_for_all +import Simplex.Chat.Migrations.M20240122_indexes import Simplex.Messaging.Agent.Store.SQLite.Migrations (Migration (..)) schemaMigrations :: [(String, Query, Maybe Query)] @@ -187,7 +191,11 @@ schemaMigrations = ("20231126_remote_ctrl_address", m20231126_remote_ctrl_address, Just down_m20231126_remote_ctrl_address), ("20231207_chat_list_pagination", m20231207_chat_list_pagination, Just down_m20231207_chat_list_pagination), ("20231214_item_content_tag", m20231214_item_content_tag, Just down_m20231214_item_content_tag), - ("20231215_recreate_msg_deliveries", m20231215_recreate_msg_deliveries, Just down_m20231215_recreate_msg_deliveries) + ("20231215_recreate_msg_deliveries", m20231215_recreate_msg_deliveries, Just down_m20231215_recreate_msg_deliveries), + ("20240102_note_folders", m20240102_note_folders, Just down_m20240102_note_folders), + ("20240104_members_profile_update", m20240104_members_profile_update, Just down_m20240104_members_profile_update), + ("20240115_block_member_for_all", m20240115_block_member_for_all, Just down_m20240115_block_member_for_all), + ("20240122_indexes", m20240122_indexes, Just down_m20240122_indexes) ] -- | The list of migrations in ascending order by date diff --git a/src/Simplex/Chat/Store/NoteFolders.hs b/src/Simplex/Chat/Store/NoteFolders.hs new file mode 100644 index 0000000000..e8336a73d8 --- /dev/null +++ b/src/Simplex/Chat/Store/NoteFolders.hs @@ -0,0 +1,69 @@ +{-# LANGUAGE DuplicateRecordFields #-} +{-# LANGUAGE LambdaCase #-} +{-# LANGUAGE NamedFieldPuns #-} +{-# LANGUAGE OverloadedStrings #-} +{-# LANGUAGE QuasiQuotes #-} +{-# LANGUAGE ScopedTypeVariables #-} + +module Simplex.Chat.Store.NoteFolders where + +import Control.Monad.Except (ExceptT (..), throwError) +import Control.Monad.IO.Class (liftIO) +import Data.Time (getCurrentTime) +import Database.SQLite.Simple (Only (..)) +import Database.SQLite.Simple.QQ (sql) +import Simplex.Chat.Store.Shared (StoreError (..)) +import Simplex.Chat.Types (NoteFolder (..), NoteFolderId, User (..)) +import Simplex.Messaging.Agent.Protocol (UserId) +import Simplex.Messaging.Agent.Store.SQLite (firstRow) +import qualified Simplex.Messaging.Agent.Store.SQLite.DB as DB + +createNoteFolder :: DB.Connection -> User -> ExceptT StoreError IO () +createNoteFolder db User {userId} = do + liftIO (DB.query db "SELECT note_folder_id FROM note_folders WHERE user_id = ? LIMIT 1" $ Only userId) >>= \case + [] -> liftIO $ DB.execute db "INSERT INTO note_folders (user_id) VALUES (?)" (Only userId) + Only noteFolderId : _ -> throwError $ SENoteFolderAlreadyExists noteFolderId + +getUserNoteFolderId :: DB.Connection -> User -> ExceptT StoreError IO NoteFolderId +getUserNoteFolderId db User {userId} = + ExceptT . firstRow fromOnly SEUserNoteFolderNotFound $ + DB.query db "SELECT note_folder_id FROM note_folders WHERE user_id = ?" (Only userId) + +getNoteFolder :: DB.Connection -> User -> NoteFolderId -> ExceptT StoreError IO NoteFolder +getNoteFolder db User {userId} noteFolderId = + ExceptT . firstRow toNoteFolder (SENoteFolderNotFound noteFolderId) $ + DB.query + db + [sql| + SELECT + created_at, updated_at, chat_ts, favorite, unread_chat + FROM note_folders + WHERE user_id = ? + AND note_folder_id = ? + |] + (userId, noteFolderId) + where + toNoteFolder (createdAt, updatedAt, chatTs, favorite, unread) = + NoteFolder {noteFolderId, userId, createdAt, updatedAt, chatTs, favorite, unread} + +updateNoteFolderUnreadChat :: DB.Connection -> User -> NoteFolder -> Bool -> IO () +updateNoteFolderUnreadChat db User {userId} NoteFolder {noteFolderId} unreadChat = do + updatedAt <- getCurrentTime + DB.execute db "UPDATE note_folders SET unread_chat = ?, updated_at = ? WHERE user_id = ? AND note_folder_id = ?" (unreadChat, updatedAt, userId, noteFolderId) + +deleteNoteFolderFiles :: DB.Connection -> UserId -> NoteFolder -> IO () +deleteNoteFolderFiles db userId NoteFolder {noteFolderId} = do + DB.execute + db + [sql| + DELETE FROM files + WHERE user_id = ? + AND chat_item_id IN ( + SELECT chat_item_id FROM chat_items WHERE user_id = ? AND note_folder_id = ? + ) + |] + (userId, userId, noteFolderId) + +deleteNoteFolderCIs :: DB.Connection -> User -> NoteFolder -> IO () +deleteNoteFolderCIs db User {userId} NoteFolder {noteFolderId} = + DB.execute db "DELETE FROM chat_items WHERE user_id = ? AND note_folder_id = ?" (userId, noteFolderId) diff --git a/src/Simplex/Chat/Store/Profiles.hs b/src/Simplex/Chat/Store/Profiles.hs index c5781a1cfe..bffdb2a6d3 100644 --- a/src/Simplex/Chat/Store/Profiles.hs +++ b/src/Simplex/Chat/Store/Profiles.hs @@ -27,6 +27,7 @@ module Simplex.Chat.Store.Profiles getUserByARcvFileId, getUserByContactId, getUserByGroupId, + getUserByNoteFolderId, getUserByFileId, getUserFileInfo, deleteUserRecord, @@ -120,7 +121,7 @@ createUserRecordAt db (AgentUserId auId) Profile {displayName, fullName, image, (profileId, displayName, userId, True, currentTs, currentTs, currentTs) contactId <- insertedRowId db DB.execute db "UPDATE users SET contact_id = ? WHERE user_id = ?" (contactId, userId) - pure $ toUser $ (userId, auId, contactId, profileId, activeUser, displayName, fullName, image, Nothing, userPreferences) :. (showNtfs, sendRcptsContacts, sendRcptsSmallGroups, Nothing, Nothing) + pure $ toUser $ (userId, auId, contactId, profileId, activeUser, displayName, fullName, image, Nothing, userPreferences) :. (showNtfs, sendRcptsContacts, sendRcptsSmallGroups, Nothing, Nothing, Nothing) getUsersInfo :: DB.Connection -> IO [UserInfo] getUsersInfo db = getUsers db >>= mapM getUserInfo @@ -200,6 +201,11 @@ getUserByGroupId db groupId = ExceptT . firstRow toUser (SEUserNotFoundByGroupId groupId) $ DB.query db (userQuery <> " JOIN groups g ON g.user_id = u.user_id WHERE g.group_id = ?") (Only groupId) +getUserByNoteFolderId :: DB.Connection -> NoteFolderId -> ExceptT StoreError IO User +getUserByNoteFolderId db contactId = + ExceptT . firstRow toUser (SEUserNotFoundByContactId contactId) $ + DB.query db (userQuery <> " JOIN note_folders nf ON nf.user_id = u.user_id WHERE nf.note_folder_id = ?") (Only contactId) + getUserByFileId :: DB.Connection -> FileTransferId -> ExceptT StoreError IO User getUserByFileId db fileId = ExceptT . firstRow toUser (SEUserNotFoundByFileId fileId) $ @@ -246,23 +252,32 @@ updateUserGroupReceipts db User {userId} UserMsgReceiptSettings {enable, clearOv updateUserProfile :: DB.Connection -> User -> Profile -> ExceptT StoreError IO User updateUserProfile db user p' - | displayName == newName = do - liftIO $ updateContactProfile_ db userId profileId p' - pure user {profile, fullPreferences} + | displayName == newName = liftIO $ do + updateContactProfile_ db userId profileId p' + currentTs <- getCurrentTime + userMemberProfileUpdatedAt' <- updateUserMemberProfileUpdatedAt_ currentTs + pure user {profile, fullPreferences, userMemberProfileUpdatedAt = userMemberProfileUpdatedAt'} | otherwise = checkConstraint SEDuplicateName . liftIO $ do currentTs <- getCurrentTime DB.execute db "UPDATE users SET local_display_name = ?, updated_at = ? WHERE user_id = ?" (newName, currentTs, userId) + userMemberProfileUpdatedAt' <- updateUserMemberProfileUpdatedAt_ currentTs DB.execute db "INSERT INTO display_names (local_display_name, ldn_base, user_id, created_at, updated_at) VALUES (?,?,?,?,?)" (newName, newName, userId, currentTs, currentTs) updateContactProfile_' db userId profileId p' currentTs - updateContact_ db userId userContactId localDisplayName newName currentTs - pure user {localDisplayName = newName, profile, fullPreferences} + updateContactLDN_ db userId userContactId localDisplayName newName currentTs + pure user {localDisplayName = newName, profile, fullPreferences, userMemberProfileUpdatedAt = userMemberProfileUpdatedAt'} where - User {userId, userContactId, localDisplayName, profile = LocalProfile {profileId, displayName, localAlias}} = user - Profile {displayName = newName, preferences} = p' + updateUserMemberProfileUpdatedAt_ currentTs + | userMemberProfileChanged = do + DB.execute db "UPDATE users SET user_member_profile_updated_at = ? WHERE user_id = ?" (currentTs, userId) + pure $ Just currentTs + | otherwise = pure userMemberProfileUpdatedAt + userMemberProfileChanged = newName /= displayName || newFullName /= fullName || newImage /= image + User {userId, userContactId, localDisplayName, profile = LocalProfile {profileId, displayName, fullName, image, localAlias}, userMemberProfileUpdatedAt} = user + Profile {displayName = newName, fullName = newFullName, image = newImage, preferences} = p' profile = toLocalProfile profileId p' localAlias fullPreferences = mergePreferences Nothing preferences @@ -296,7 +311,7 @@ getUserContactProfiles db User {userId} = |] (Only userId) where - toContactProfile :: (ContactName, Text, Maybe ImageData, Maybe ConnReqContact, Maybe Preferences) -> (Profile) + toContactProfile :: (ContactName, Text, Maybe ImageData, Maybe ConnReqContact, Maybe Preferences) -> Profile toContactProfile (displayName, fullName, image, contactLink, preferences) = Profile {displayName, fullName, image, contactLink, preferences} createUserContactLink :: DB.Connection -> User -> ConnId -> ConnReqContact -> SubscriptionMode -> ExceptT StoreError IO () diff --git a/src/Simplex/Chat/Store/Shared.hs b/src/Simplex/Chat/Store/Shared.hs index a5f4f0e0e5..e4d47b32cc 100644 --- a/src/Simplex/Chat/Store/Shared.hs +++ b/src/Simplex/Chat/Store/Shared.hs @@ -69,6 +69,9 @@ data StoreError | SEDuplicateGroupMember | SEGroupAlreadyJoined | SEGroupInvitationNotFound + | SENoteFolderAlreadyExists {noteFolderId :: NoteFolderId} + | SENoteFolderNotFound {noteFolderId :: NoteFolderId} + | SEUserNoteFolderNotFound | SESndFileNotFound {fileId :: FileTransferId} | SESndFileInvalid {fileId :: FileTransferId} | SERcvFileNotFound {fileId :: FileTransferId} @@ -76,6 +79,7 @@ data StoreError | SEFileNotFound {fileId :: FileTransferId} | SERcvFileInvalid {fileId :: FileTransferId} | SERcvFileInvalidDescrPart + | SELocalFileNoTransfer {fileId :: FileTransferId} | SESharedMsgIdNotFoundByFileId {fileId :: FileTransferId} | SEFileIdNotFoundBySharedMsgId {sharedMsgId :: SharedMsgId} | SESndFileNotFoundXFTP {agentSndFileId :: AgentSndFileId} @@ -309,15 +313,15 @@ userQuery :: Query userQuery = [sql| SELECT u.user_id, u.agent_user_id, u.contact_id, ucp.contact_profile_id, u.active_user, u.local_display_name, ucp.full_name, ucp.image, ucp.contact_link, ucp.preferences, - u.show_ntfs, u.send_rcpts_contacts, u.send_rcpts_small_groups, u.view_pwd_hash, u.view_pwd_salt + u.show_ntfs, u.send_rcpts_contacts, u.send_rcpts_small_groups, u.view_pwd_hash, u.view_pwd_salt, u.user_member_profile_updated_at FROM users u JOIN contacts uct ON uct.contact_id = u.contact_id JOIN contact_profiles ucp ON ucp.contact_profile_id = uct.contact_profile_id |] -toUser :: (UserId, UserId, ContactId, ProfileId, Bool, ContactName, Text, Maybe ImageData, Maybe ConnReqContact, Maybe Preferences) :. (Bool, Bool, Bool, Maybe B64UrlByteString, Maybe B64UrlByteString) -> User -toUser ((userId, auId, userContactId, profileId, activeUser, displayName, fullName, image, contactLink, userPreferences) :. (showNtfs, sendRcptsContacts, sendRcptsSmallGroups, viewPwdHash_, viewPwdSalt_)) = - User {userId, agentUserId = AgentUserId auId, userContactId, localDisplayName = displayName, profile, activeUser, fullPreferences, showNtfs, sendRcptsContacts, sendRcptsSmallGroups, viewPwdHash} +toUser :: (UserId, UserId, ContactId, ProfileId, Bool, ContactName, Text, Maybe ImageData, Maybe ConnReqContact, Maybe Preferences) :. (Bool, Bool, Bool, Maybe B64UrlByteString, Maybe B64UrlByteString, Maybe UTCTime) -> User +toUser ((userId, auId, userContactId, profileId, activeUser, displayName, fullName, image, contactLink, userPreferences) :. (showNtfs, sendRcptsContacts, sendRcptsSmallGroups, viewPwdHash_, viewPwdSalt_, userMemberProfileUpdatedAt)) = + User {userId, agentUserId = AgentUserId auId, userContactId, localDisplayName = displayName, profile, activeUser, fullPreferences, showNtfs, sendRcptsContacts, sendRcptsSmallGroups, viewPwdHash, userMemberProfileUpdatedAt} where profile = LocalProfile {profileId, displayName, fullName, image, contactLink, preferences = userPreferences, localAlias = ""} fullPreferences = mergePreferences Nothing userPreferences diff --git a/src/Simplex/Chat/Terminal.hs b/src/Simplex/Chat/Terminal.hs index c27675678e..2060e529eb 100644 --- a/src/Simplex/Chat/Terminal.hs +++ b/src/Simplex/Chat/Terminal.hs @@ -1,12 +1,16 @@ {-# LANGUAGE DuplicateRecordFields #-} {-# LANGUAGE FlexibleContexts #-} +{-# LANGUAGE NamedFieldPuns #-} {-# LANGUAGE OverloadedStrings #-} module Simplex.Chat.Terminal where import Control.Exception (handle, throwIO) import Control.Monad +import qualified Data.ByteArray as BA import qualified Data.List.NonEmpty as L +import qualified Data.Text as T +import Data.Text.Encoding (encodeUtf8) import Database.SQLite.Simple (SQLError (..)) import qualified Database.SQLite.Simple as DB import Simplex.Chat (defaultChatConfig) @@ -19,7 +23,7 @@ import Simplex.Chat.Terminal.Output import Simplex.FileTransfer.Client.Presets (defaultXFTPServers) import Simplex.Messaging.Client (defaultNetworkConfig) import Simplex.Messaging.Util (raceAny_) -import System.Exit (exitFailure) +import System.IO (hFlush, hSetEcho, stdin, stdout) terminalChatConfig :: ChatConfig terminalChatConfig = @@ -40,18 +44,29 @@ terminalChatConfig = } simplexChatTerminal :: WithTerminal t => ChatConfig -> ChatOpts -> t -> IO () -simplexChatTerminal cfg opts t = - handle checkDBKeyError . simplexChatCore cfg opts $ \u cc -> do - ct <- newChatTerminal t opts - when (firstTime cc) . printToTerminal ct $ chatWelcome u - runChatTerminal ct cc opts - -checkDBKeyError :: SQLError -> IO () -checkDBKeyError e = case sqlError e of - DB.ErrorNotADatabase -> do - putStrLn "Database file is invalid or you passed an incorrect encryption key" - exitFailure - _ -> throwIO e +simplexChatTerminal cfg options t = run options + where + run opts@ChatOpts {coreOptions = coreOptions@CoreChatOpts {dbKey}} = + handle checkDBKeyError . simplexChatCore cfg opts $ \u cc -> do + ct <- newChatTerminal t opts + when (firstTime cc) . printToTerminal ct $ chatWelcome u + runChatTerminal ct cc opts + where + checkDBKeyError :: SQLError -> IO () + checkDBKeyError e = case sqlError e of + DB.ErrorNotADatabase -> do + putStrLn $ "Database file is invalid or " <> if BA.null dbKey then "encrypted." else "you passed an incorrect encryption key." + run =<< getKeyOpts + _ -> throwIO e + getKeyOpts :: IO ChatOpts + getKeyOpts = do + putStr "Enter database encryption key (Ctrl-C to exit):" + hFlush stdout + hSetEcho stdin False + key <- getLine + hSetEcho stdin True + putStrLn "" + pure opts {coreOptions = coreOptions {dbKey = BA.convert $ encodeUtf8 $ T.pack key}} runChatTerminal :: ChatTerminal -> ChatController -> ChatOpts -> IO () runChatTerminal ct cc opts = raceAny_ [runTerminalInput ct cc, runTerminalOutput ct cc opts, runInputLoop ct cc] diff --git a/src/Simplex/Chat/Types.hs b/src/Simplex/Chat/Types.hs index b69f18f8f7..e65e1a916f 100644 --- a/src/Simplex/Chat/Types.hs +++ b/src/Simplex/Chat/Types.hs @@ -35,6 +35,7 @@ import Data.Int (Int64) import Data.Maybe (isJust) import Data.Text (Text) import qualified Data.Text as T +import Data.Text.Encoding (encodeUtf8) import Data.Time.Clock (UTCTime) import Data.Typeable (Typeable) import Database.SQLite.Simple (ResultError (..), SQLData (..)) @@ -50,7 +51,7 @@ import Simplex.Messaging.Crypto.File (CryptoFileArgs (..)) import Simplex.Messaging.Encoding.String import Simplex.Messaging.Parsers (defaultJSON, dropPrefix, enumJSON, fromTextField_, sumTypeJSON, taggedObjectJSON) import Simplex.Messaging.Protocol (ProtoServerWithAuth, ProtocolTypeI) -import Simplex.Messaging.Util ((<$?>)) +import Simplex.Messaging.Util (safeDecodeUtf8, (<$?>)) import Simplex.Messaging.Version class IsContact a where @@ -60,21 +61,21 @@ class IsContact a where preferences' :: a -> Maybe Preferences instance IsContact User where - contactId' = userContactId + contactId' User {userContactId} = userContactId {-# INLINE contactId' #-} - profile' = profile + profile' User {profile} = profile {-# INLINE profile' #-} - localDisplayName' = localDisplayName + localDisplayName' User {localDisplayName} = localDisplayName {-# INLINE localDisplayName' #-} preferences' User {profile = LocalProfile {preferences}} = preferences {-# INLINE preferences' #-} instance IsContact Contact where - contactId' = contactId + contactId' Contact {contactId} = contactId {-# INLINE contactId' #-} - profile' = profile + profile' Contact {profile} = profile {-# INLINE profile' #-} - localDisplayName' = localDisplayName + localDisplayName' Contact {localDisplayName} = localDisplayName {-# INLINE localDisplayName' #-} preferences' Contact {profile = LocalProfile {preferences}} = preferences {-# INLINE preferences' #-} @@ -112,7 +113,8 @@ data User = User viewPwdHash :: Maybe UserPwdHash, showNtfs :: Bool, sendRcptsContacts :: Bool, - sendRcptsSmallGroups :: Bool + sendRcptsSmallGroups :: Bool, + userMemberProfileUpdatedAt :: Maybe UTCTime } deriving (Show) @@ -346,7 +348,8 @@ data GroupInfo = GroupInfo chatSettings :: ChatSettings, createdAt :: UTCTime, updatedAt :: UTCTime, - chatTs :: Maybe UTCTime + chatTs :: Maybe UTCTime, + userMemberProfileSentAt :: Maybe UTCTime } deriving (Eq, Show) @@ -481,6 +484,10 @@ profilesMatch LocalProfile {displayName = n2, fullName = fn2, image = i2} = n1 == n2 && fn1 == fn2 && i1 == i2 +redactedMemberProfile :: Profile -> Profile +redactedMemberProfile Profile {displayName, fullName, image} = + Profile {displayName, fullName, image, contactLink = Nothing, preferences = Nothing} + data IncognitoProfile = NewIncognito Profile | ExistingIncognito LocalProfile type LocalAlias = Text @@ -590,9 +597,55 @@ data MemberInfo = MemberInfo memberInfo :: GroupMember -> MemberInfo memberInfo GroupMember {memberId, memberRole, memberProfile, activeConn} = - MemberInfo memberId memberRole cvr (fromLocalProfile memberProfile) - where - cvr = ChatVersionRange . fromJVersionRange . peerChatVRange <$> activeConn + MemberInfo + { memberId, + memberRole, + v = ChatVersionRange . fromJVersionRange . peerChatVRange <$> activeConn, + profile = redactedMemberProfile $ fromLocalProfile memberProfile + } + +data MemberRestrictionStatus + = MRSBlocked + | MRSUnrestricted + | MRSUnknown Text + deriving (Eq, Show) + +instance FromField MemberRestrictionStatus where fromField = fromBlobField_ strDecode + +instance ToField MemberRestrictionStatus where toField = toField . strEncode + +instance StrEncoding MemberRestrictionStatus where + strEncode = \case + MRSBlocked -> "blocked" + MRSUnrestricted -> "unrestricted" + MRSUnknown tag -> encodeUtf8 tag + strDecode s = Right $ case s of + "blocked" -> MRSBlocked + "unrestricted" -> MRSUnrestricted + tag -> MRSUnknown $ safeDecodeUtf8 tag + strP = strDecode <$?> A.takeByteString + +instance FromJSON MemberRestrictionStatus where + parseJSON = strParseJSON "MemberRestrictionStatus" + +instance ToJSON MemberRestrictionStatus where + toJSON = strToJSON + toEncoding = strToJEncoding + +mrsBlocked :: MemberRestrictionStatus -> Bool +mrsBlocked = \case + MRSBlocked -> True + _ -> False + +data MemberRestrictions = MemberRestrictions + { restriction :: MemberRestrictionStatus + } + deriving (Eq, Show) + +memberRestrictions :: GroupMember -> Maybe MemberRestrictions +memberRestrictions m + | blockedByAdmin m = Just MemberRestrictions {restriction = MRSBlocked} + | otherwise = Nothing data ReceivedGroupInvitation = ReceivedGroupInvitation { fromMember :: GroupMember, @@ -613,6 +666,7 @@ data GroupMember = GroupMember memberCategory :: GroupMemberCategory, memberStatus :: GroupMemberStatus, memberSettings :: GroupMemberSettings, + blockedByAdmin :: Bool, invitedBy :: InvitedBy, invitedByGroupMemberId :: Maybe GroupMemberId, localDisplayName :: ContactName, @@ -673,6 +727,7 @@ data NewGroupMember = NewGroupMember { memInfo :: MemberInfo, memCategory :: GroupMemberCategory, memStatus :: GroupMemberStatus, + memRestriction :: Maybe MemberRestrictionStatus, memInvitedBy :: InvitedBy, memInvitedByGroupMemberId :: Maybe GroupMemberId, localDisplayName :: ContactName, @@ -825,6 +880,7 @@ data GroupMemberStatus = GSMemRemoved -- member who was removed from the group | GSMemLeft -- member who left the group | GSMemGroupDeleted -- user member of the deleted group + | GSMemUnknown -- unknown member, whose message was forwarded by an admin (likely member wasn't introduced due to not being a current member, but message was included in history) | GSMemInvited -- member is sent to or received invitation to join the group | GSMemIntroduced -- user received x.grp.mem.intro for this member (only with GCPreMember) | GSMemIntroInvited -- member is sent to or received from intro invitation @@ -851,6 +907,7 @@ memberActive m = case memberStatus m of GSMemRemoved -> False GSMemLeft -> False GSMemGroupDeleted -> False + GSMemUnknown -> False GSMemInvited -> False GSMemIntroduced -> False GSMemIntroInvited -> False @@ -869,6 +926,7 @@ memberCurrent' = \case GSMemRemoved -> False GSMemLeft -> False GSMemGroupDeleted -> False + GSMemUnknown -> False GSMemInvited -> False GSMemIntroduced -> True GSMemIntroInvited -> True @@ -883,6 +941,7 @@ memberRemoved m = case memberStatus m of GSMemRemoved -> True GSMemLeft -> True GSMemGroupDeleted -> True + GSMemUnknown -> False GSMemInvited -> False GSMemIntroduced -> False GSMemIntroInvited -> False @@ -897,6 +956,7 @@ instance TextEncoding GroupMemberStatus where "removed" -> Just GSMemRemoved "left" -> Just GSMemLeft "deleted" -> Just GSMemGroupDeleted + "unknown" -> Just GSMemUnknown "invited" -> Just GSMemInvited "introduced" -> Just GSMemIntroduced "intro-inv" -> Just GSMemIntroInvited @@ -910,6 +970,7 @@ instance TextEncoding GroupMemberStatus where GSMemRemoved -> "removed" GSMemLeft -> "left" GSMemGroupDeleted -> "deleted" + GSMemUnknown -> "unknown" GSMemInvited -> "invited" GSMemIntroduced -> "introduced" GSMemIntroInvited -> "intro-inv" @@ -1158,6 +1219,15 @@ data FileTransferMeta = FileTransferMeta } deriving (Eq, Show) +data LocalFileMeta = LocalFileMeta + { fileId :: FileTransferId, + fileName :: String, + filePath :: String, + fileSize :: Integer, + fileCryptoArgs :: Maybe CryptoFileArgs + } + deriving (Eq, Show) + data XFTPSndFile = XFTPSndFile { agentSndFileId :: AgentSndFileId, privateSndFileDescr :: Maybe Text, @@ -1522,6 +1592,20 @@ data XGrpMemIntroCont = XGrpMemIntroCont } deriving (Show) +-- | Entity for local chats +data NoteFolder = NoteFolder + { noteFolderId :: NoteFolderId, + userId :: UserId, + createdAt :: UTCTime, + updatedAt :: UTCTime, + chatTs :: UTCTime, + favorite :: Bool, + unread :: Bool + } + deriving (Eq, Show) + +type NoteFolderId = Int64 + data ServerCfg p = ServerCfg { server :: ProtoServerWithAuth p, preset :: Bool, @@ -1606,6 +1690,8 @@ $(JQ.deriveJSON defaultJSON ''IntroInvitation) $(JQ.deriveJSON defaultJSON ''MemberInfo) +$(JQ.deriveJSON defaultJSON ''MemberRestrictions) + $(JQ.deriveJSON defaultJSON ''GroupMemberRef) $(JQ.deriveJSON defaultJSON ''FileDescr) @@ -1628,6 +1714,8 @@ $(JQ.deriveJSON defaultJSON ''XFTPSndFile) $(JQ.deriveJSON defaultJSON ''FileTransferMeta) +$(JQ.deriveJSON defaultJSON ''LocalFileMeta) + $(JQ.deriveJSON (sumTypeJSON $ dropPrefix "FT") ''FileTransfer) $(JQ.deriveJSON defaultJSON ''UserPwdHash) @@ -1642,6 +1730,8 @@ $(JQ.deriveJSON defaultJSON ''Contact) $(JQ.deriveJSON defaultJSON ''ContactRef) +$(JQ.deriveJSON defaultJSON ''NoteFolder) + instance ProtocolTypeI p => ToJSON (ServerCfg p) where toEncoding = $(JQ.mkToEncoding defaultJSON ''ServerCfg) toJSON = $(JQ.mkToJSON defaultJSON ''ServerCfg) diff --git a/src/Simplex/Chat/Types/Preferences.hs b/src/Simplex/Chat/Types/Preferences.hs index 0597ee48cf..2286ae8f40 100644 --- a/src/Simplex/Chat/Types/Preferences.hs +++ b/src/Simplex/Chat/Types/Preferences.hs @@ -14,6 +14,7 @@ {-# LANGUAGE TypeApplications #-} {-# LANGUAGE TypeFamilyDependencies #-} {-# OPTIONS_GHC -Wno-unrecognised-pragmas #-} +{-# OPTIONS_GHC -fno-warn-ambiguous-fields #-} {-# HLINT ignore "Use newtype instead of data" #-} @@ -77,7 +78,7 @@ allChatFeatures = ] chatPrefSel :: SChatFeature f -> Preferences -> Maybe (FeaturePreference f) -chatPrefSel = \case +chatPrefSel f Preferences {timedMessages, fullDelete, reactions, voice, calls} = case f of SCFTimedMessages -> timedMessages SCFFullDelete -> fullDelete SCFReactions -> reactions @@ -102,7 +103,7 @@ instance PreferenceI (Maybe Preferences) where getPreference f prefs = fromMaybe (getPreference f defaultChatPrefs) (chatPrefSel f =<< prefs) instance PreferenceI FullPreferences where - getPreference = \case + getPreference f FullPreferences {timedMessages, fullDelete, reactions, voice, calls} = case f of SCFTimedMessages -> timedMessages SCFFullDelete -> fullDelete SCFReactions -> reactions @@ -182,21 +183,19 @@ groupFeatureAllowed' :: GroupFeatureI f => SGroupFeature f -> FullGroupPreferenc groupFeatureAllowed' feature prefs = getField @"enable" (getGroupPreference feature prefs) == FEOn -allGroupFeatureItems :: [AGroupFeature] -allGroupFeatureItems = +allGroupFeatures :: [AGroupFeature] +allGroupFeatures = [ AGF SGFTimedMessages, AGF SGFDirectMessages, AGF SGFFullDelete, AGF SGFReactions, AGF SGFVoice, - AGF SGFFiles + AGF SGFFiles, + AGF SGFHistory ] -allGroupFeatures :: [AGroupFeature] -allGroupFeatures = allGroupFeatureItems <> [AGF SGFHistory] - groupPrefSel :: SGroupFeature f -> GroupPreferences -> Maybe (GroupFeaturePreference f) -groupPrefSel = \case +groupPrefSel f GroupPreferences {timedMessages, directMessages, fullDelete, reactions, voice, files, history} = case f of SGFTimedMessages -> timedMessages SGFDirectMessages -> directMessages SGFFullDelete -> fullDelete @@ -225,7 +224,7 @@ instance GroupPreferenceI (Maybe GroupPreferences) where getGroupPreference pt prefs = fromMaybe (getGroupPreference pt defaultGroupPrefs) (groupPrefSel pt =<< prefs) instance GroupPreferenceI FullGroupPreferences where - getGroupPreference = \case + getGroupPreference f FullGroupPreferences {timedMessages, directMessages, fullDelete, reactions, voice, files, history} = case f of SGFTimedMessages -> timedMessages SGFDirectMessages -> directMessages SGFFullDelete -> fullDelete @@ -382,19 +381,19 @@ class (Eq (FeaturePreference f), HasField "allow" (FeaturePreference f) FeatureA prefParam :: FeaturePreference f -> Maybe Int instance HasField "allow" TimedMessagesPreference FeatureAllowed where - hasField p = (\allow -> p {allow}, allow (p :: TimedMessagesPreference)) + hasField p@TimedMessagesPreference {allow} = (\a -> p {allow = a}, allow) instance HasField "allow" FullDeletePreference FeatureAllowed where - hasField p = (\allow -> p {allow}, allow (p :: FullDeletePreference)) + hasField p@FullDeletePreference {allow} = (\a -> p {allow = a}, allow) instance HasField "allow" ReactionsPreference FeatureAllowed where - hasField p = (\allow -> p {allow}, allow (p :: ReactionsPreference)) + hasField p@ReactionsPreference {allow} = (\a -> p {allow = a}, allow) instance HasField "allow" VoicePreference FeatureAllowed where - hasField p = (\allow -> p {allow}, allow (p :: VoicePreference)) + hasField p@VoicePreference {allow} = (\a -> p {allow = a}, allow) instance HasField "allow" CallsPreference FeatureAllowed where - hasField p = (\allow -> p {allow}, allow (p :: CallsPreference)) + hasField p@CallsPreference {allow} = (\a -> p {allow = a}, allow) instance FeatureI 'CFTimedMessages where type FeaturePreference 'CFTimedMessages = TimedMessagesPreference @@ -461,28 +460,28 @@ class (Eq (GroupFeaturePreference f), HasField "enable" (GroupFeaturePreference groupPrefParam :: GroupFeaturePreference f -> Maybe Int instance HasField "enable" GroupPreference GroupFeatureEnabled where - hasField p = (\enable -> p {enable}, enable (p :: GroupPreference)) + hasField p@GroupPreference {enable} = (\e -> p {enable = e}, enable) instance HasField "enable" TimedMessagesGroupPreference GroupFeatureEnabled where - hasField p = (\enable -> p {enable}, enable (p :: TimedMessagesGroupPreference)) + hasField p@TimedMessagesGroupPreference {enable} = (\e -> p {enable = e}, enable) instance HasField "enable" DirectMessagesGroupPreference GroupFeatureEnabled where - hasField p = (\enable -> p {enable}, enable (p :: DirectMessagesGroupPreference)) + hasField p@DirectMessagesGroupPreference {enable} = (\e -> p {enable = e}, enable) instance HasField "enable" ReactionsGroupPreference GroupFeatureEnabled where - hasField p = (\enable -> p {enable}, enable (p :: ReactionsGroupPreference)) + hasField p@ReactionsGroupPreference {enable} = (\e -> p {enable = e}, enable) instance HasField "enable" FullDeleteGroupPreference GroupFeatureEnabled where - hasField p = (\enable -> p {enable}, enable (p :: FullDeleteGroupPreference)) + hasField p@FullDeleteGroupPreference {enable} = (\e -> p {enable = e}, enable) instance HasField "enable" VoiceGroupPreference GroupFeatureEnabled where - hasField p = (\enable -> p {enable}, enable (p :: VoiceGroupPreference)) + hasField p@VoiceGroupPreference {enable} = (\e -> p {enable = e}, enable) instance HasField "enable" FilesGroupPreference GroupFeatureEnabled where - hasField p = (\enable -> p {enable}, enable (p :: FilesGroupPreference)) + hasField p@FilesGroupPreference {enable} = (\e -> p {enable = e}, enable) instance HasField "enable" HistoryGroupPreference GroupFeatureEnabled where - hasField p = (\enable -> p {enable}, enable (p :: HistoryGroupPreference)) + hasField p@HistoryGroupPreference {enable} = (\e -> p {enable = e}, enable) instance GroupFeatureI 'GFTimedMessages where type GroupFeaturePreference 'GFTimedMessages = TimedMessagesGroupPreference @@ -720,7 +719,7 @@ preferenceState pref = in (allow, param) getContactUserPreference :: SChatFeature f -> ContactUserPreferences -> ContactUserPreference (FeaturePreference f) -getContactUserPreference = \case +getContactUserPreference f ContactUserPreferences {timedMessages, fullDelete, reactions, voice, calls} = case f of SCFTimedMessages -> timedMessages SCFFullDelete -> fullDelete SCFReactions -> reactions diff --git a/src/Simplex/Chat/View.hs b/src/Simplex/Chat/View.hs index b328ce9c03..05c90696b4 100644 --- a/src/Simplex/Chat/View.hs +++ b/src/Simplex/Chat/View.hs @@ -178,6 +178,9 @@ responseToView hu@(currentRH, user_) ChatConfig {logLevel, showReactions, showRe CRGroupLinkConnecting u g _ -> ttyUser u [ttyGroup' g <> ": joining the group..."] CRUserDeletedMember u g m -> ttyUser u [ttyGroup' g <> ": you removed " <> ttyMember m <> " from the group"] CRLeftMemberUser u g -> ttyUser u $ [ttyGroup' g <> ": you left the group"] <> groupPreserved g + CRUnknownMemberCreated u g fwdM um -> ttyUser u [ttyGroup' g <> ": " <> ttyMember fwdM <> " forwarded a message from an unknown member, creating unknown member record " <> ttyMember um] + CRUnknownMemberBlocked u g byM um -> ttyUser u [ttyGroup' g <> ": " <> ttyMember byM <> " blocked an unknown member, creating unknown member record " <> ttyMember um] + CRUnknownMemberAnnounced u g _ um m -> ttyUser u [ttyGroup' g <> ": unknown member " <> ttyMember um <> " updated to " <> ttyMember m] CRGroupDeletedUser u g -> ttyUser u [ttyGroup' g <> ": you deleted the group"] CRRcvFileDescrReady _ _ -> [] CRRcvFileDescrNotReady _ _ -> [] @@ -211,7 +214,9 @@ responseToView hu@(currentRH, user_) ChatConfig {logLevel, showReactions, showRe CRContactConnecting u _ -> ttyUser u [] CRContactConnected u ct userCustomProfile -> ttyUser u $ viewContactConnected ct userCustomProfile testView CRContactAnotherClient u c -> ttyUser u [ttyContact' c <> ": contact is connected to another client"] - CRSubscriptionEnd u acEntity -> ttyUser u [sShow (connId (entityConnection acEntity :: Connection)) <> ": END"] + CRSubscriptionEnd u acEntity -> + let Connection {connId} = entityConnection acEntity + in ttyUser u [sShow connId <> ": END"] CRContactsDisconnected srv cs -> [plain $ "server disconnected " <> showSMPServer srv <> " (" <> contactList cs <> ")"] CRContactsSubscribed srv cs -> [plain $ "server connected " <> showSMPServer srv <> " (" <> contactList cs <> ")"] CRContactSubError u c e -> ttyUser u [ttyContact' c <> ": contact error " <> sShow e] @@ -239,6 +244,8 @@ responseToView hu@(currentRH, user_) ChatConfig {logLevel, showReactions, showRe CRConnectedToGroupMember u g m _ -> ttyUser u [ttyGroup' g <> ": " <> connectedMember m <> " is connected"] CRMemberRole u g by m r r' -> ttyUser u $ viewMemberRoleChanged g by m r r' CRMemberRoleUser u g m r r' -> ttyUser u $ viewMemberRoleUserChanged g m r r' + CRMemberBlockedForAll u g by m blocked -> ttyUser u $ viewMemberBlockedForAll g by m blocked + CRMemberBlockedForAllUser u g m blocked -> ttyUser u $ viewMemberBlockedForAllUser g m blocked CRDeletedMemberUser u g by -> ttyUser u $ [ttyGroup' g <> ": " <> ttyMember by <> " removed you from the group"] <> groupPreserved g CRDeletedMember u g by m -> ttyUser u [ttyGroup' g <> ": " <> ttyMember by <> " removed " <> ttyMember m <> " from the group"] CRLeftMember u g m -> ttyUser u [ttyGroup' g <> ": " <> ttyMember m <> " left the group"] @@ -351,6 +358,11 @@ responseToView hu@(currentRH, user_) ChatConfig {logLevel, showReactions, showRe ("active subscriptions:" : map sShow activeSubscriptions) <> ("pending subscriptions: " : map sShow pendingSubscriptions) <> ("removed subscriptions: " : map sShow removedSubscriptions) + CRAgentWorkersSummary {agentWorkersSummary} -> ["agent workers summary: " <> plain (LB.unpack $ J.encode agentWorkersSummary)] + CRAgentWorkersDetails {agentWorkersDetails} -> + [ "agent workers details:", + plain . LB.unpack $ J.encode agentWorkersDetails -- this would be huge, but copypastable when has its own line + ] CRConnectionDisabled entity -> viewConnectionEntityDisabled entity CRAgentRcvQueueDeleted acId srv aqId err_ -> [ ("completed deleting rcv queue, agent connection id: " <> sShow acId) @@ -392,6 +404,7 @@ responseToView hu@(currentRH, user_) ChatConfig {logLevel, showReactions, showRe toChatView :: AChat -> (Text, Text, Maybe ConnStatus) toChatView (AChat _ (Chat (DirectChat Contact {localDisplayName, activeConn}) items _)) = ("@" <> localDisplayName, toCIPreview items Nothing, connStatus <$> activeConn) toChatView (AChat _ (Chat (GroupChat GroupInfo {membership, localDisplayName}) items _)) = ("#" <> localDisplayName, toCIPreview items (Just membership), Nothing) + toChatView (AChat _ (Chat (LocalChat _) items _)) = ("*", toCIPreview items Nothing, Nothing) toChatView (AChat _ (Chat (ContactRequest UserContactRequest {localDisplayName}) items _)) = ("<@" <> localDisplayName, toCIPreview items Nothing, Nothing) toChatView (AChat _ (Chat (ContactConnection PendingContactConnection {pccConnId, pccConnStatus}) items _)) = (":" <> T.pack (show pccConnId), toCIPreview items Nothing, Just pccConnStatus) toCIPreview :: [CChatItem c] -> Maybe GroupMember -> Text @@ -426,21 +439,16 @@ responseToView hu@(currentRH, user_) ChatConfig {logLevel, showReactions, showRe unmuted' :: User -> ChatInfo c -> CIDirection c d -> Bool -> [StyledString] -> [StyledString] unmuted' u chat chatDir mention s | chatDirNtf u chat chatDir mention = s + | testView = map (<> " <muted>") s | otherwise = [] userNtf :: User -> Bool userNtf User {showNtfs, activeUser} = showNtfs || activeUser -chatNtf :: User -> ChatInfo c -> Bool -> Bool -chatNtf user cInfo mention = case cInfo of - DirectChat ct -> contactNtf user ct mention - GroupChat g -> groupNtf user g mention - _ -> False - chatDirNtf :: User -> ChatInfo c -> CIDirection c d -> Bool -> Bool chatDirNtf user cInfo chatDir mention = case (cInfo, chatDir) of (DirectChat ct, CIDirectRcv) -> contactNtf user ct mention - (GroupChat g, CIGroupRcv m) -> groupNtf user g mention && showMessages (memberSettings m) + (GroupChat g, CIGroupRcv m) -> groupNtf user g mention && not (blockedByAdmin m) && showMessages (memberSettings m) _ -> True contactNtf :: User -> Contact -> Bool -> Bool @@ -463,6 +471,7 @@ chatItemDeletedText ChatItem {meta = CIMeta {itemDeleted}, content} membership_ CIModerated _ m -> markedDeleted content <> byMember m CIDeleted _ -> markedDeleted content CIBlocked _ -> "blocked" + CIBlockedByAdmin _ -> "blocked by admin" markedDeleted = \case CISndModerated -> "deleted" CIRcvModerated -> "deleted" @@ -545,12 +554,30 @@ viewChatItem chat ci@ChatItem {chatDir, meta = meta@CIMeta {forwardedByMember}, CIRcvIntegrityError err -> viewRcvIntegrityError from err ts tz meta CIRcvGroupInvitation {} -> showRcvItemProhibited from CIRcvModerated {} -> receivedWithTime_ ts tz (ttyFromGroup g m) quote meta [plainContent content] False + CIRcvBlocked {} -> receivedWithTime_ ts tz (ttyFromGroup g m) quote meta [plainContent content] False _ -> showRcvItem from where from = ttyFromGroup g m where quote = maybe [] (groupQuote g) quotedItem - _ -> [] + LocalChat _ -> case chatDir of + CILocalSnd -> case content of + CISndMsgContent mc -> hideLive meta $ withLocalFile to $ sndMsg to quote mc + CISndGroupEvent {} -> showSndItemProhibited to + _ -> showSndItem to + where + to = "* " + CILocalRcv -> case content of + CIRcvMsgContent mc -> withLocalFile from $ rcvMsg from quote mc + CIRcvIntegrityError err -> viewRcvIntegrityError from err ts tz meta + CIRcvGroupEvent {} -> showRcvItemProhibited from + _ -> showRcvItem from + where + from = "* " + where + quote = [] + ContactRequest {} -> [] + ContactConnection {} -> [] withItemDeleted item = case chatItemDeletedText ci (chatInfoMembership chat) of Nothing -> item Just t -> item <> styled (colored Red) (" [" <> t <> "]") @@ -559,6 +586,7 @@ viewChatItem chat ci@ChatItem {chatDir, meta = meta@CIMeta {forwardedByMember}, Just _ -> item <> styled (colored Yellow) (" [>>]" :: String) withSndFile = withFile viewSentFileInvitation withRcvFile = withFile viewReceivedFileInvitation + withLocalFile = withFile viewLocalFile withFile view dir l = maybe l (\f -> l <> view dir f ts tz meta) file sndMsg = msg viewSentMessage rcvMsg = msg viewReceivedMessage @@ -702,8 +730,15 @@ viewItemReaction showReactions chat CIReaction {chatDir, chatItem = CChatItem md where from = ttyFromGroup g m reactionMsg mc = quoteText mc . ttyQuotedMember . Just $ sentByMember' g itemDir + (LocalChat _, CILocalRcv) -> case ciMsgContent content of + Just mc -> view from $ reactionMsg mc + _ -> [] + where + from = "* " + reactionMsg mc = quoteText mc $ if toMsgDirection md == MDSnd then ">>" else ">" (_, CIDirectSnd) -> [sentText] (_, CIGroupSnd) -> [sentText] + (_, CILocalSnd) -> [sentText] where view from msg | showReactions = viewReceivedReaction from msg reactionText ts tz sentAt @@ -943,6 +978,14 @@ viewMemberRoleUserChanged g@GroupInfo {membership} m r r' where view s = [ttyGroup' g <> ": you changed " <> s <> " from " <> showRole r <> " to " <> showRole r'] +viewMemberBlockedForAll :: GroupInfo -> GroupMember -> GroupMember -> Bool -> [StyledString] +viewMemberBlockedForAll g by m blocked = + [ttyGroup' g <> ": " <> ttyMember by <> " " <> (if blocked then "blocked" else "unblocked") <> " " <> ttyMember m] + +viewMemberBlockedForAllUser :: GroupInfo -> GroupMember -> Bool -> [StyledString] +viewMemberBlockedForAllUser g m blocked = + [ttyGroup' g <> ": you " <> (if blocked then "blocked" else "unblocked") <> " " <> ttyMember m] + showRole :: GroupMemberRole -> StyledString showRole = plain . strEncode @@ -952,7 +995,7 @@ viewGroupMembers (Group GroupInfo {membership} members) = map groupMember . filt removedOrLeft m = let s = memberStatus m in s == GSMemRemoved || s == GSMemLeft groupMember m = memIncognito m <> ttyFullMember m <> ": " <> plain (intercalate ", " $ [role m] <> category m <> status m <> muted m) role :: GroupMember -> String - role m = B.unpack . strEncode $ memberRole (m :: GroupMember) + role GroupMember {memberRole} = B.unpack $ strEncode memberRole category m = case memberCategory m of GCUserMember -> ["you"] GCInviteeMember -> ["invited"] @@ -961,14 +1004,16 @@ viewGroupMembers (Group GroupInfo {membership} members) = map groupMember . filt status m = case memberStatus m of GSMemRemoved -> ["removed"] GSMemLeft -> ["left"] + GSMemUnknown -> ["status unknown"] GSMemInvited -> ["not yet joined"] GSMemConnected -> ["connected"] GSMemComplete -> ["connected"] GSMemCreator -> ["created group"] _ -> [] muted m - | showMessages (memberSettings m) = [] - | otherwise = ["blocked"] + | blockedByAdmin m = ["blocked by admin"] + | not (showMessages $ memberSettings m) = ["blocked"] + | otherwise = [] viewContactConnected :: Contact -> Maybe Profile -> Bool -> [StyledString] viewContactConnected ct userIncognitoProfile testView = @@ -990,7 +1035,7 @@ viewGroupsList [] = ["you have no groups!", "to create: " <> highlight' "/g <nam viewGroupsList gs = map groupSS $ sortOn (ldn_ . fst) gs where ldn_ :: GroupInfo -> Text - ldn_ = T.toLower . (localDisplayName :: GroupInfo -> GroupName) + ldn_ GroupInfo {localDisplayName} = T.toLower localDisplayName groupSS (g@GroupInfo {membership, chatSettings = ChatSettings {enableNtfs}}, GroupSummary {currentMembers}) = case memberStatus membership of GSMemInvited -> groupInvitation' g @@ -1129,11 +1174,12 @@ viewGroupInfo GroupInfo {groupId} s = ] viewGroupMemberInfo :: GroupInfo -> GroupMember -> Maybe ConnectionStats -> [StyledString] -viewGroupMemberInfo GroupInfo {groupId} m@GroupMember {groupMemberId, memberProfile = LocalProfile {localAlias}, activeConn} stats = +viewGroupMemberInfo GroupInfo {groupId} m@GroupMember {groupMemberId, memberProfile = LocalProfile {localAlias, contactLink}, activeConn} stats = [ "group ID: " <> sShow groupId, "member ID: " <> sShow groupMemberId ] <> maybe ["member not connected"] viewConnectionStats stats + <> maybe [] (\l -> ["contact address: " <> (plain . strEncode) (simplexChatContact l)]) contactLink <> ["alias: " <> plain localAlias | localAlias /= ""] <> [viewConnectionVerified (memberSecurityCode m) | isJust stats] <> maybe [] (\ac -> [viewPeerChatVRange (peerChatVRange ac)]) activeConn @@ -1564,6 +1610,11 @@ receivingFile_' hu testView status (AChatItem _ _ chat ChatItem {file = Just CIF _ -> [] receivingFile_' _ _ status _ = [plain status <> " receiving file"] -- shouldn't happen +viewLocalFile :: StyledString -> CIFile d -> CurrentTime -> TimeZone -> CIMeta c d -> [StyledString] +viewLocalFile to CIFile {fileId, fileSource} ts tz = case fileSource of + Just (CryptoFile fPath _) -> sentWithTime_ ts tz [to <> fileTransferStr fileId fPath] + _ -> const [] + cryptoFileArgsStr :: Bool -> CryptoFileArgs -> ByteString cryptoFileArgsStr testView cfArgs@(CFArgs key nonce) | testView = LB.toStrict $ J.encode cfArgs @@ -1775,7 +1826,7 @@ viewChatError logLevel testView = \case CEUserNotHidden _ -> ["user is not hidden"] CEInvalidDisplayName {displayName, validName} -> map plain $ - ["invalid display name: " <> viewName displayName] + [if T.null displayName then "display name can't be empty" else "invalid display name: " <> viewName displayName] <> ["you could use this one: " <> viewName validName | not (T.null validName)] CEChatNotStarted -> ["error: chat not started"] CEChatNotStopped -> ["error: chat not stopped"] @@ -1805,6 +1856,13 @@ viewChatError logLevel testView = \case CEGroupContactRole c -> ["contact " <> ttyContact c <> " has insufficient permissions for this group action"] CEGroupNotJoined g -> ["you did not join this group, use " <> highlight ("/join #" <> viewGroupName g)] CEGroupMemberNotActive -> ["your group connection is not active yet, try later"] + CECantBlockMemberForSelf g m showMsgs -> + [ "admins or above can't block member for self, use " + <> highlight + ( (if showMsgs then "/unblock for all" else "/block for all") + <> (" #" <> viewGroupName g <> " " <> viewMemberName m) + ) + ] CEGroupMemberUserRemoved -> ["you are no longer a member of the group"] CEGroupMemberNotFound -> ["group doesn't have this member"] CEGroupMemberIntroNotFound c -> ["group member intro not found for " <> ttyContact c] @@ -1870,6 +1928,7 @@ viewChatError logLevel testView = \case SEDuplicateGroupMessage {groupId, sharedMsgId} | testView -> ["duplicate group message, group id: " <> sShow groupId <> ", message id: " <> sShow sharedMsgId] | otherwise -> [] + SEUserNoteFolderNotFound -> ["no notes folder"] e -> ["chat db error: " <> sShow e] ChatErrorDatabase err -> case err of DBErrorEncrypted -> ["error: chat database is already encrypted"] @@ -1887,6 +1946,8 @@ viewChatError logLevel testView = \case AGENT A_DUPLICATE -> [withConnEntity <> "error: AGENT A_DUPLICATE" | logLevel == CLLDebug] AGENT A_PROHIBITED -> [withConnEntity <> "error: AGENT A_PROHIBITED" | logLevel <= CLLWarning] CONN NOT_FOUND -> [withConnEntity <> "error: CONN NOT_FOUND" | logLevel <= CLLWarning] + CRITICAL restart e -> [plain $ "critical error: " <> e] <> ["please restart the app" | restart] + INTERNAL e -> [plain $ "internal error: " <> e] e -> [withConnEntity <> "smp agent error: " <> sShow e | logLevel <= CLLWarning] where withConnEntity = case entity_ of @@ -1905,7 +1966,7 @@ viewChatError logLevel testView = \case "[" <> connEntityLabel entity <> ", userContactLinkId: " <> sShow userContactLinkId <> ", connId: " <> cId conn <> "] " Nothing -> "" cId :: Connection -> StyledString - cId conn = sShow (connId (conn :: Connection)) + cId Connection {connId} = sShow connId ChatErrorRemoteCtrl e -> [plain $ "remote controller error: " <> show e] ChatErrorRemoteHost RHNew e -> [plain $ "new remote host error: " <> show e] ChatErrorRemoteHost (RHId rhId) e -> [plain $ "remote host " <> show rhId <> " error: " <> show e] diff --git a/tests/Bots/BroadcastTests.hs b/tests/Bots/BroadcastTests.hs index 12eaff11c2..95c80d6345 100644 --- a/tests/Bots/BroadcastTests.hs +++ b/tests/Bots/BroadcastTests.hs @@ -12,10 +12,10 @@ import Control.Concurrent (forkIO, killThread, threadDelay) import Control.Exception (bracket) import Simplex.Chat.Bot.KnownContacts import Simplex.Chat.Core -import Simplex.Chat.Options (ChatOpts (..), CoreChatOpts (..)) +import Simplex.Chat.Options (CoreChatOpts (..)) import Simplex.Chat.Types (Profile (..)) import System.FilePath ((</>)) -import Test.Hspec +import Test.Hspec hiding (it) broadcastBotTests :: SpecWith FilePath broadcastBotTests = do @@ -33,7 +33,7 @@ broadcastBotProfile = Profile {displayName = "broadcast_bot", fullName = "Broadc mkBotOpts :: FilePath -> [KnownContact] -> BroadcastBotOpts mkBotOpts tmp publishers = BroadcastBotOpts - { coreOptions = (coreOptions (testOpts :: ChatOpts)) {dbFilePrefix = tmp </> botDbPrefix}, + { coreOptions = testCoreOpts {dbFilePrefix = tmp </> botDbPrefix}, publishers, welcomeMessage = defaultWelcomeMessage publishers, prohibitedMessage = defaultWelcomeMessage publishers diff --git a/tests/Bots/DirectoryTests.hs b/tests/Bots/DirectoryTests.hs index b33f4f569f..1054a1d8eb 100644 --- a/tests/Bots/DirectoryTests.hs +++ b/tests/Bots/DirectoryTests.hs @@ -18,10 +18,10 @@ import GHC.IO.Handle (hClose) import Simplex.Chat.Bot.KnownContacts import Simplex.Chat.Controller (ChatConfig (..)) import Simplex.Chat.Core -import Simplex.Chat.Options (ChatOpts (..), CoreChatOpts (..)) +import Simplex.Chat.Options (CoreChatOpts (..)) import Simplex.Chat.Types (GroupMemberRole (..), Profile (..)) import System.FilePath ((</>)) -import Test.Hspec +import Test.Hspec hiding (it) directoryServiceTests :: SpecWith FilePath directoryServiceTests = do @@ -63,7 +63,7 @@ directoryProfile = Profile {displayName = "SimpleX-Directory", fullName = "", im mkDirectoryOpts :: FilePath -> [KnownContact] -> DirectoryOpts mkDirectoryOpts tmp superUsers = DirectoryOpts - { coreOptions = (coreOptions (testOpts :: ChatOpts)) {dbFilePrefix = tmp </> serviceDbPrefix}, + { coreOptions = testCoreOpts {dbFilePrefix = tmp </> serviceDbPrefix}, superUsers, directoryLog = Just $ tmp </> "directory_service.log", serviceName = "SimpleX-Directory", diff --git a/tests/ChatClient.hs b/tests/ChatClient.hs index 759182b51a..f7982c5fb4 100644 --- a/tests/ChatClient.hs +++ b/tests/ChatClient.hs @@ -36,6 +36,7 @@ import Simplex.FileTransfer.Server.Env (XFTPServerConfig (..), defaultFileExpira import Simplex.Messaging.Agent.Env.SQLite import Simplex.Messaging.Agent.RetryInterval import Simplex.Messaging.Agent.Store.SQLite (MigrationConfirmation (..)) +import qualified Simplex.Messaging.Agent.Store.SQLite.DB as DB import Simplex.Messaging.Client (ProtocolClientConfig (..), defaultNetworkConfig) import Simplex.Messaging.Server (runSMPServerBlocking) import Simplex.Messaging.Server.Env.STM @@ -58,25 +59,11 @@ serverPort = "7001" testOpts :: ChatOpts testOpts = ChatOpts - { coreOptions = - CoreChatOpts - { dbFilePrefix = undefined, - dbKey = "", - -- dbKey = "this is a pass-phrase to encrypt the database", - smpServers = ["smp://LcJUMfVhwD8yxjAiSaDzzGF3-kLG4Uh0Fl_ZIjrRwjI=:server_password@localhost:7001"], - xftpServers = ["xftp://LcJUMfVhwD8yxjAiSaDzzGF3-kLG4Uh0Fl_ZIjrRwjI=:server_password@localhost:7002"], - networkConfig = defaultNetworkConfig, - logLevel = CLLImportant, - logConnections = False, - logServerHosts = False, - logAgent = Nothing, - logFile = Nothing, - tbqSize = 16, - highlyAvailable = False - }, + { coreOptions = testCoreOpts, deviceName = Nothing, chatCmd = "", chatCmdDelay = 3, + chatCmdLog = CCLNone, chatServerPort = Nothing, optFilesFolder = Nothing, showReactions = True, @@ -87,8 +74,26 @@ testOpts = maintenance = False } +testCoreOpts :: CoreChatOpts +testCoreOpts = + CoreChatOpts + { dbFilePrefix = undefined, + dbKey = "", + -- dbKey = "this is a pass-phrase to encrypt the database", + smpServers = ["smp://LcJUMfVhwD8yxjAiSaDzzGF3-kLG4Uh0Fl_ZIjrRwjI=:server_password@localhost:7001"], + xftpServers = ["xftp://LcJUMfVhwD8yxjAiSaDzzGF3-kLG4Uh0Fl_ZIjrRwjI=:server_password@localhost:7002"], + networkConfig = defaultNetworkConfig, + logLevel = CLLImportant, + logConnections = False, + logServerHosts = False, + logAgent = Nothing, + logFile = Nothing, + tbqSize = 16, + highlyAvailable = False + } + getTestOpts :: Bool -> ScrubbedBytes -> ChatOpts -getTestOpts maintenance dbKey = testOpts {maintenance, coreOptions = (coreOptions testOpts) {dbKey}} +getTestOpts maintenance dbKey = testOpts {maintenance, coreOptions = testCoreOpts {dbKey}} termSettings :: VirtualTerminalSettings termSettings = @@ -188,7 +193,8 @@ groupLinkViaContactVRange = mkVersionRange 1 2 createTestChat :: FilePath -> ChatConfig -> ChatOpts -> String -> Profile -> IO TestCC createTestChat tmp cfg opts@ChatOpts {coreOptions = CoreChatOpts {dbKey}} dbPrefix profile = do - Right db@ChatDatabase {chatStore} <- createChatDatabase (tmp </> dbPrefix) dbKey False MCError + Right db@ChatDatabase {chatStore, agentStore} <- createChatDatabase (tmp </> dbPrefix) dbKey False MCError + withTransaction agentStore (`DB.execute_` "INSERT INTO users (user_id) VALUES (1);") Right user <- withTransaction chatStore $ \db' -> runExceptT $ createUserRecord db' (AgentUserId 1) profile True startTestChat_ db cfg opts user diff --git a/tests/ChatTests.hs b/tests/ChatTests.hs index a00274a541..77d256a240 100644 --- a/tests/ChatTests.hs +++ b/tests/ChatTests.hs @@ -4,13 +4,15 @@ import ChatTests.ChatList import ChatTests.Direct import ChatTests.Files import ChatTests.Groups +import ChatTests.Local import ChatTests.Profiles -import Test.Hspec +import Test.Hspec hiding (it) chatTests :: SpecWith FilePath chatTests = do describe "direct tests" chatDirectTests describe "group tests" chatGroupTests + describe "local chats tests" chatLocalChatsTests describe "file tests" chatFileTests describe "profile tests" chatProfileTests describe "chat list pagination tests" chatListTests diff --git a/tests/ChatTests/ChatList.hs b/tests/ChatTests/ChatList.hs index f42067c7e5..8492ab0f0d 100644 --- a/tests/ChatTests/ChatList.hs +++ b/tests/ChatTests/ChatList.hs @@ -4,7 +4,7 @@ import ChatClient import ChatTests.Utils import Data.Time.Clock (getCurrentTime) import Data.Time.Format.ISO8601 (iso8601Show) -import Test.Hspec +import Test.Hspec hiding (it) chatListTests :: SpecWith FilePath chatListTests = do @@ -191,17 +191,23 @@ testPaginationAllChatTypes = connectUsers alice dan alice <##> dan - ts6 <- iso8601Show <$> getCurrentTime + _ts6 <- iso8601Show <$> getCurrentTime - getChats_ alice "count=10" [("@dan", "hey"), ("#team", ""), (":3", ""), ("<@cath", ""), ("@bob", "hey")] - getChats_ alice "count=3" [("@dan", "hey"), ("#team", ""), (":3", "")] + -- * (notes) + createCCNoteFolder alice + alice /* "psst" + + ts7 <- iso8601Show <$> getCurrentTime + + getChats_ alice "count=10" [("*", "psst"), ("@dan", "hey"), ("#team", ""), (":3", ""), ("<@cath", ""), ("@bob", "hey")] + getChats_ alice "count=3" [("*", "psst"), ("@dan", "hey"), ("#team", "")] getChats_ alice ("after=" <> ts2 <> " count=2") [(":3", ""), ("<@cath", "")] getChats_ alice ("before=" <> ts5 <> " count=2") [("#team", ""), (":3", "")] - getChats_ alice ("after=" <> ts3 <> " count=10") [("@dan", "hey"), ("#team", ""), (":3", "")] + getChats_ alice ("after=" <> ts3 <> " count=10") [("*", "psst"), ("@dan", "hey"), ("#team", ""), (":3", "")] getChats_ alice ("before=" <> ts4 <> " count=10") [(":3", ""), ("<@cath", ""), ("@bob", "hey")] - getChats_ alice ("after=" <> ts1 <> " count=10") [("@dan", "hey"), ("#team", ""), (":3", ""), ("<@cath", ""), ("@bob", "hey")] - getChats_ alice ("before=" <> ts6 <> " count=10") [("@dan", "hey"), ("#team", ""), (":3", ""), ("<@cath", ""), ("@bob", "hey")] - getChats_ alice ("after=" <> ts6 <> " count=10") [] + getChats_ alice ("after=" <> ts1 <> " count=10") [("*", "psst"), ("@dan", "hey"), ("#team", ""), (":3", ""), ("<@cath", ""), ("@bob", "hey")] + getChats_ alice ("before=" <> ts7 <> " count=10") [("*", "psst"), ("@dan", "hey"), ("#team", ""), (":3", ""), ("<@cath", ""), ("@bob", "hey")] + getChats_ alice ("after=" <> ts7 <> " count=10") [] getChats_ alice ("before=" <> ts1 <> " count=10") [] let queryFavorite = "{\"type\": \"filters\", \"favorite\": true, \"unread\": false}" diff --git a/tests/ChatTests/Direct.hs b/tests/ChatTests/Direct.hs index a53bbff3d2..8e7f8536ee 100644 --- a/tests/ChatTests/Direct.hs +++ b/tests/ChatTests/Direct.hs @@ -24,7 +24,7 @@ import qualified Simplex.Messaging.Crypto as C import Simplex.Messaging.Version import System.Directory (copyFile, doesDirectoryExist, doesFileExist) import System.FilePath ((</>)) -import Test.Hspec +import Test.Hspec hiding (it) chatDirectTests :: SpecWith FilePath chatDirectTests = do @@ -1180,7 +1180,7 @@ testMuteContact = bob ##> "/mute @alice" bob <## "ok" alice #> "@bob hi" - (bob </) + bob <# "alice> hi <muted>" bob ##> "/contacts" bob <## "alice (Alice) (muted, you can /unmute @alice)" bob ##> "/unmute @alice" @@ -1204,7 +1204,7 @@ testMuteGroup = bob <## "ok" alice #> "#team hi" concurrently_ - (bob </) + (bob <# "#team alice> hi <muted>") (cath <# "#team alice> hi") bob #> "#team hello" concurrently_ @@ -1214,7 +1214,9 @@ testMuteGroup = cath <# "#team > bob hello" cath <## " hello too!" concurrentlyN_ - [ (bob </), + [ do + bob <# "#team cath> > bob hello <muted>" + bob <## " hello too! <muted>", do alice <# "#team cath> > bob hello" alice <## " hello too!" @@ -1236,7 +1238,9 @@ testMuteGroup = alice <# "#team > cath hello too!" alice <## " hey cath!" concurrentlyN_ - [ (bob </), + [ do + bob <# "#team alice> > cath hello too! <muted>" + bob <## " hey cath! <muted>", do cath <# "#team alice> > cath hello too!" cath <## " hey cath!" @@ -1245,20 +1249,32 @@ testMuteGroup = bob <## "#team (3 members, mentions only, you can /unmute #team)" bob ##> "/unmute #team" bob <## "ok" + + threadDelay 1000000 + alice #> "#team hi again" concurrently_ (bob <# "#team alice> hi again") (cath <# "#team alice> hi again") bob ##> "/block #team alice" + bob <## "admins or above can't block member for self, use /block for all #team alice" + -- can bypass with api + bob ##> "/_member settings #1 1 {\"showMessages\": false}" bob <## "ok" bob ##> "/ms team" bob <## "bob (Bob): admin, you, connected" bob <## "alice (Alice): owner, host, connected, blocked" bob <## "cath (Catherine): admin, connected" + + threadDelay 1000000 + alice #> "#team test 1" concurrently_ - (bob </) + (bob <# "#team alice> test 1 [blocked] <muted>") (cath <# "#team alice> test 1") + + threadDelay 1000000 + cath #> "#team test 2" concurrently_ (bob <# "#team cath> test 2") @@ -1269,6 +1285,9 @@ testMuteGroup = bob <# "#team cath> test 2" threadDelay 1000000 bob ##> "/unblock #team alice" + bob <## "admins or above can't block member for self, use /unblock for all #team alice" + -- can bypass with api + bob ##> "/_member settings #1 1 {\"showMessages\": true}" bob <## "ok" bob ##> "/ms team" bob <## "bob (Bob): admin, you, connected" @@ -1386,14 +1405,14 @@ testMultipleUserAddresses = cLinkAlisa <- getContactLink alice True bob ##> ("/c " <> cLinkAlisa) alice <#? bob - alice #$> ("/_get chats 2 pcc=on", chats, [("<@bob", "")]) + alice #$> ("/_get chats 2 pcc=on", chats, [("<@bob", ""), ("*", "")]) alice ##> "/ac bob" alice <## "bob (Bob): accepting contact request..." concurrently_ (bob <## "alisa: contact is connected") (alice <## "bob (Bob): contact is connected") threadDelay 100000 - alice #$> ("/_get chats 2 pcc=on", chats, [("@bob", lastChatFeature)]) + alice #$> ("/_get chats 2 pcc=on", chats, [("@bob", lastChatFeature), ("*", "")]) alice <##> bob bob #> "@alice hey alice" @@ -1424,7 +1443,7 @@ testMultipleUserAddresses = (cath <## "alisa: contact is connected") (alice <## "cath (Catherine): contact is connected") threadDelay 100000 - alice #$> ("/_get chats 2 pcc=on", chats, [("@cath", lastChatFeature), ("@bob", "hey")]) + alice #$> ("/_get chats 2 pcc=on", chats, [("@cath", lastChatFeature), ("@bob", "hey"), ("*", "")]) alice <##> cath -- first user doesn't have cath as contact @@ -1559,6 +1578,19 @@ testDeleteUser = alice ##> "/create user alisa3" showActiveUser alice "alisa3" + alice ##> "/delete user alisa3 del_smp=on" + alice <### ["ok", "completed deleting user"] + alice ##> "/users" + alice <## "no users" + + alice ##> "/create user alisa4" + showActiveUser alice "alisa4" + connectUsers alice bob + alice <##> bob + alice ##> "/delete user alisa4 del_smp=on" + alice <### ["ok", "completed deleting user"] + alice ##> "/users" + alice <## "no users" testUsersDifferentCIExpirationTTL :: HasCallStack => FilePath -> IO () testUsersDifferentCIExpirationTTL tmp = do diff --git a/tests/ChatTests/Files.hs b/tests/ChatTests/Files.hs index b987bbf5e0..a6b0f56ba3 100644 --- a/tests/ChatTests/Files.hs +++ b/tests/ChatTests/Files.hs @@ -21,7 +21,7 @@ import Simplex.Messaging.Crypto.File (CryptoFile (..), CryptoFileArgs (..)) import Simplex.Messaging.Encoding.String import Simplex.Messaging.Util (unlessM) import System.Directory (copyFile, createDirectoryIfMissing, doesFileExist, getFileSize) -import Test.Hspec +import Test.Hspec hiding (it) chatFileTests :: SpecWith FilePath chatFileTests = do diff --git a/tests/ChatTests/Groups.hs b/tests/ChatTests/Groups.hs index 76bc520aa4..51a5b352a7 100644 --- a/tests/ChatTests/Groups.hs +++ b/tests/ChatTests/Groups.hs @@ -19,7 +19,7 @@ import qualified Simplex.Messaging.Agent.Store.SQLite.DB as DB import Simplex.Messaging.Version import System.Directory (copyFile) import System.FilePath ((</>)) -import Test.Hspec +import Test.Hspec hiding (it) chatGroupTests :: SpecWith FilePath chatGroupTests = do @@ -131,6 +131,22 @@ chatGroupTests = do it "quoted messages" testGroupHistoryQuotes it "deleted message is not included" testGroupHistoryDeletedMessage it "disappearing message is sent as disappearing" testGroupHistoryDisappearingMessage + it "welcome message (group description) is sent after history" testGroupHistoryWelcomeMessage + it "unknown member messages are processed" testGroupHistoryUnknownMember + describe "membership profile updates" $ do + it "send profile update on next message to group" testMembershipProfileUpdateNextGroupMessage + it "multiple groups with same member, update is applied only once" testMembershipProfileUpdateSameMember + it "member contact is active" testMembershipProfileUpdateContactActive + it "member contact is deleted" testMembershipProfileUpdateContactDeleted + it "member contact is deleted silently, then considered disabled" testMembershipProfileUpdateContactDisabled + it "profile update without change is ignored" testMembershipProfileUpdateNoChangeIgnored + it "change of profile contact link is ignored" testMembershipProfileUpdateContactLinkIgnored + describe "block member for all" $ do + it "messages are marked blocked" testBlockForAllMarkedBlocked + it "messages are fully deleted" testBlockForAllFullDelete + it "another admin can unblock" testBlockForAllAnotherAdminUnblocks + it "member was blocked before joining group" testBlockForAllBeforeJoining + it "can't repeat block, unblock" testBlockForAllCantRepeat where _0 = supportedChatVRange -- don't create direct connections _1 = groupCreateDirectVRange @@ -2681,7 +2697,7 @@ testGroupLinkNoContact = ] threadDelay 100000 - alice #$> ("/_get chat #1 count=100", chat, [(0, "invited via your group link"), (0, "connected")]) + alice #$> ("/_get chat #1 count=100", chat, [(1, "Recent history: off"), (0, "invited via your group link"), (0, "connected")]) alice @@@ [("#team", "connected")] bob @@@ [("#team", "connected")] @@ -2744,7 +2760,7 @@ testGroupLinkNoContactInviteesWereConnected = ] threadDelay 100000 - alice #$> ("/_get chat #1 count=100", chat, [(0, "invited via your group link"), (0, "connected")]) + alice #$> ("/_get chat #1 count=100", chat, [(1, "Recent history: off"), (0, "invited via your group link"), (0, "connected")]) alice @@@ [("#team", "connected")] bob @@@ [("#team", "connected"), ("@cath", "hey")] @@ -2825,7 +2841,7 @@ testGroupLinkNoContactAllMembersWereConnected = ] threadDelay 100000 - alice #$> ("/_get chat #1 count=100", chat, [(0, "invited via your group link"), (0, "connected")]) + alice #$> ("/_get chat #1 count=100", chat, [(1, "Recent history: off"), (0, "invited via your group link"), (0, "connected")]) alice @@@ [("#team", "connected"), ("@bob", "hey"), ("@cath", "hey")] bob @@@ [("#team", "connected"), ("@alice", "hey"), ("@cath", "hey")] @@ -4124,12 +4140,10 @@ testMemberContactProfileUpdate = bob <# "#team alice> hello" cath <# "#team alice> hello" - bob #> "#team hello too" - alice <# "#team rob> hello too" - cath <# "#team bob> hello too" -- not updated profile - cath #> "#team hello there" - alice <# "#team kate> hello there" - bob <# "#team cath> hello there" -- not updated profile + alice `hasContactProfiles` ["alice", "rob", "kate"] + bob `hasContactProfiles` ["rob", "alice", "cath"] + cath `hasContactProfiles` ["kate", "alice", "bob"] + bob `send` "@cath hi" bob <### [ "member #team cath does not have direct connection, creating", @@ -5048,7 +5062,8 @@ testGroupHistoryDeletedMessage = testGroupHistoryDisappearingMessage :: HasCallStack => FilePath -> IO () testGroupHistoryDisappearingMessage = testChat3 aliceProfile bobProfile cathProfile $ - \alice bob cath -> do + -- \alice bob cath -> do -- revert when test is stable + \a b c -> withTestOutput a $ \alice -> withTestOutput b $ \bob -> withTestOutput c $ \cath -> do createGroup2 "team" alice bob threadDelay 1000000 @@ -5059,12 +5074,12 @@ testGroupHistoryDisappearingMessage = threadDelay 1000000 -- 3 seconds so that messages 2 and 3 are not deleted for alice before sending history to cath - alice ##> "/set disappear #team on 3" + alice ##> "/set disappear #team on 4" alice <## "updated group preferences:" - alice <## "Disappearing messages: on (3 sec)" + alice <## "Disappearing messages: on (4 sec)" bob <## "alice updated group #team:" bob <## "updated group preferences:" - bob <## "Disappearing messages: on (3 sec)" + bob <## "Disappearing messages: on (4 sec)" bob #> "#team 2" alice <# "#team bob> 2" @@ -5109,15 +5124,18 @@ testGroupHistoryDisappearingMessage = r1 `shouldContain` [(0, "1"), (0, "2"), (0, "3"), (0, "4")] concurrentlyN_ - [ do - alice <## "timed message deleted: 2" - alice <## "timed message deleted: 3", - do - bob <## "timed message deleted: 2" - bob <## "timed message deleted: 3", - do - cath <## "timed message deleted: 2" - cath <## "timed message deleted: 3" + [ alice + <### [ "timed message deleted: 2", + "timed message deleted: 3" + ], + bob + <### [ "timed message deleted: 2", + "timed message deleted: 3" + ], + cath + <### [ "timed message deleted: 2", + "timed message deleted: 3" + ] ] cath ##> "/_get chat #1 count=100" @@ -5125,3 +5143,874 @@ testGroupHistoryDisappearingMessage = r2 `shouldContain` [(0, "1"), (0, "4")] r2 `shouldNotContain` [(0, "2")] r2 `shouldNotContain` [(0, "3")] + +testGroupHistoryWelcomeMessage :: HasCallStack => FilePath -> IO () +testGroupHistoryWelcomeMessage = + testChat3 aliceProfile bobProfile cathProfile $ + \alice bob cath -> do + createGroup2 "team" alice bob + + alice ##> "/set welcome #team welcome to team" + alice <## "description changed to:" + alice <## "welcome to team" + + bob <## "alice updated group #team:" + bob <## "description changed to:" + bob <## "welcome to team" + + threadDelay 1000000 + + alice #> "#team hello" + bob <# "#team alice> hello" + + threadDelay 1000000 + + bob #> "#team hey!" + alice <# "#team bob> hey!" + + connectUsers alice cath + addMember "team" alice cath GRAdmin + cath ##> "/j team" + concurrentlyN_ + [ alice <## "#team: cath joined the group", + cath + <### [ "#team: you joined the group", + WithTime "#team alice> hello [>>]", + WithTime "#team bob> hey! [>>]", + WithTime "#team alice> welcome to team", + "#team: member bob (Bob) is connected" + ], + do + bob <## "#team: alice added cath (Catherine) to the group (connecting...)" + bob <## "#team: new member cath is connected" + ] + + cath ##> "/_get chat #1 count=100" + r <- chat <$> getTermLine cath + r `shouldContain` [(0, "hello"), (0, "hey!"), (0, "welcome to team")] + + -- message delivery works after sending history + alice #> "#team 1" + [bob, cath] *<# "#team alice> 1" + bob #> "#team 2" + [alice, cath] *<# "#team bob> 2" + cath #> "#team 3" + [alice, bob] *<# "#team cath> 3" + +testGroupHistoryUnknownMember :: HasCallStack => FilePath -> IO () +testGroupHistoryUnknownMember = + testChat4 aliceProfile bobProfile cathProfile danProfile $ + \alice bob cath dan -> do + createGroup3 "team" alice bob cath + + threadDelay 1000000 + + alice #> "#team hi from alice" + [bob, cath] *<# "#team alice> hi from alice" + + threadDelay 1000000 + + bob #> "#team hi from bob" + [alice, cath] *<# "#team bob> hi from bob" + + threadDelay 1000000 + + cath #> "#team hi from cath" + [alice, bob] *<# "#team cath> hi from cath" + + bob ##> "/l team" + concurrentlyN_ + [ do + bob <## "#team: you left the group" + bob <## "use /d #team to delete the group", + alice <## "#team: bob left the group", + cath <## "#team: bob left the group" + ] + + connectUsers alice dan + addMember "team" alice dan GRAdmin + dan ##> "/j team" + concurrentlyN_ + [ alice <## "#team: dan joined the group", + dan + <### [ "#team: you joined the group", + WithTime "#team alice> hi from alice [>>]", + StartsWith "#team: alice forwarded a message from an unknown member, creating unknown member record", + EndsWith "hi from bob [>>]", + WithTime "#team cath> hi from cath [>>]", + "#team: member cath (Catherine) is connected" + ], + do + cath <## "#team: alice added dan (Daniel) to the group (connecting...)" + cath <## "#team: new member dan is connected" + ] + + dan ##> "/_get chat #1 count=100" + r <- chat <$> getTermLine dan + r `shouldContain` [(0, "hi from alice"), (0, "hi from bob"), (0, "hi from cath")] + + dan ##> "/ms team" + dan + <### [ "dan (Daniel): admin, you, connected", + "alice (Alice): owner, host, connected", + "cath (Catherine): admin, connected", + EndsWith "author, status unknown" + ] + + -- message delivery works after sending history + alice #> "#team 1" + [cath, dan] *<# "#team alice> 1" + cath #> "#team 2" + [alice, dan] *<# "#team cath> 2" + dan #> "#team 3" + [alice, cath] *<# "#team dan> 3" + +testMembershipProfileUpdateNextGroupMessage :: HasCallStack => FilePath -> IO () +testMembershipProfileUpdateNextGroupMessage = + testChat3 aliceProfile bobProfile cathProfile $ + \alice bob cath -> do + -- create group 1 + alice ##> "/g team" + alice <## "group #team is created" + alice <## "to add members use /a team <name> or /create link #team" + alice ##> "/create link #team" + gLinkTeam <- getGroupLink alice "team" GRMember True + bob ##> ("/c " <> gLinkTeam) + bob <## "connection request sent!" + alice <## "bob (Bob): accepting request to join group #team..." + concurrentlyN_ + [ alice <## "#team: bob joined the group", + do + bob <## "#team: joining the group..." + bob <## "#team: you joined the group" + ] + + -- create group 2 + alice ##> "/g club" + alice <## "group #club is created" + alice <## "to add members use /a club <name> or /create link #club" + alice ##> "/create link #club" + gLinkClub <- getGroupLink alice "club" GRMember True + cath ##> ("/c " <> gLinkClub) + cath <## "connection request sent!" + alice <## "cath (Catherine): accepting request to join group #club..." + concurrentlyN_ + [ alice <## "#club: cath joined the group", + do + cath <## "#club: joining the group..." + cath <## "#club: you joined the group" + ] + + -- alice has no contacts + alice ##> "/contacts" + + alice #> "#team hello team" + bob <# "#team alice> hello team" + + alice #> "#club hello club" + cath <# "#club alice> hello club" + + alice ##> "/p alisa" + alice <## "user profile is changed to alisa (your 0 contacts are notified)" + + -- update profile in group 1 + + bob ##> "/ms team" + bob + <### [ "bob (Bob): member, you, connected", + "alice (Alice): owner, host, connected" + ] + + alice #> "#team team 1" + bob <# "#team alisa> team 1" + cath <// 50000 + + bob ##> "/ms team" + bob + <### [ "bob (Bob): member, you, connected", + "alisa: owner, host, connected" + ] + + alice #> "#team team 2" + bob <# "#team alisa> team 2" + + bob ##> "/_get chat #1 count=100" + rb <- chat <$> getTermLine bob + rb `shouldContain` [(0, "updated profile")] + + -- update profile in group 2 + + cath ##> "/ms club" + cath + <### [ "cath (Catherine): member, you, connected", + "alice (Alice): owner, host, connected" + ] + + alice #> "#club club 1" + cath <# "#club alisa> club 1" + + cath ##> "/ms club" + cath + <### [ "cath (Catherine): member, you, connected", + "alisa: owner, host, connected" + ] + + alice #> "#club club 2" + cath <# "#club alisa> club 2" + + cath ##> "/_get chat #1 count=100" + rc <- chat <$> getTermLine cath + rc `shouldContain` [(0, "updated profile")] + +testMembershipProfileUpdateSameMember :: HasCallStack => FilePath -> IO () +testMembershipProfileUpdateSameMember = + testChat2 aliceProfile bobProfile $ + \alice bob -> do + createGroup2 "team" alice bob + createGroup2' "club" alice bob False + + alice ##> "/d bob" + alice <## "bob: contact is deleted" + bob <## "alice (Alice) deleted contact with you" + + alice ##> "/p alisa" + alice <## "user profile is changed to alisa (your 0 contacts are notified)" + + bob `hasContactProfiles` ["alice", "bob"] + + alice #> "#team team 1" + bob <## "contact alice changed to alisa" + bob <## "use @alisa <message> to send messages" + bob <# "#team alisa> team 1" + + -- since members were related to the same contact, both member records are updated + bob `hasContactProfiles` ["alisa", "bob"] + checkMembers bob + checkItems bob + + -- profile update is not processed in second group, since it hasn't changed + alice #> "#club club 1" + bob <# "#club alisa> club 1" + + bob `hasContactProfiles` ["alisa", "bob"] + checkMembers bob + checkItems bob + where + checkMembers bob = do + bob ##> "/ms team" + bob + <### [ "bob (Bob): admin, you, connected", + "alisa: owner, host, connected" + ] + bob ##> "/ms club" + bob + <### [ "bob (Bob): admin, you, connected", + "alisa: owner, host, connected" + ] + checkItems bob = do + bob ##> "/_get chat @2 count=100" + rCt <- chat <$> getTermLine bob + rCt `shouldNotContain` [(0, "updated profile")] + + bob ##> "/_get chat #1 count=100" + rTeam <- chat <$> getTermLine bob + rTeam `shouldContain` [(0, "updated profile")] + + bob ##> "/_get chat #2 count=100" + rClub <- chat <$> getTermLine bob + rClub `shouldNotContain` [(0, "updated profile")] + +testMembershipProfileUpdateContactActive :: HasCallStack => FilePath -> IO () +testMembershipProfileUpdateContactActive = + testChat2 aliceProfile bobProfile $ + \alice bob -> do + createGroup2 "team" alice bob + + alice ##> "/contacts" + alice <## "bob (Bob)" + + alice #> "#team hello team" + bob <# "#team alice> hello team" + + alice ##> "/p alisa" + alice <## "user profile is changed to alisa (your 1 contacts are notified)" + bob <## "contact alice changed to alisa" + bob <## "use @alisa <message> to send messages" + + bob `hasContactProfiles` ["alisa", "bob"] + + alice #> "#team team 1" + bob <# "#team alisa> team 1" + + bob `hasContactProfiles` ["alisa", "bob"] + + checkItems bob + + alice ##> "/ad" + cLink <- getContactLink alice True + alice ##> "/pa on" + alice <## "new contact address set" + bob <## "alisa set new contact address, use /info alisa to view" + + bob `hasContactProfiles` ["alisa", "bob"] + checkAliceProfileLink bob "alisa" cLink + + -- profile update does not remove contact address from profile + alice ##> "/p 'Alice Smith'" + alice <## "user profile is changed to 'Alice Smith' (your 1 contacts are notified)" + bob <## "contact alisa changed to 'Alice Smith'" + bob <## "use @'Alice Smith' <message> to send messages" + + bob `hasContactProfiles` ["Alice Smith", "bob"] + checkAliceProfileLink bob "'Alice Smith'" cLink + + -- receiving group message does not remove contact address from profile + alice #> "#team team 2" + bob <# "#team 'Alice Smith'> team 2" + + bob `hasContactProfiles` ["Alice Smith", "bob"] + checkAliceProfileLink bob "'Alice Smith'" cLink + + checkItems bob + where + checkItems bob = do + bob ##> "/_get chat @2 count=100" + rCt <- chat <$> getTermLine bob + rCt `shouldContain` [(0, "updated profile")] + + bob ##> "/_get chat #1 count=100" + rGrp <- chat <$> getTermLine bob + rGrp `shouldNotContain` [(0, "updated profile")] + checkAliceProfileLink bob name cLink = do + bob ##> ("/info #team " <> name) + bob <## "group ID: 1" + bob <## "member ID: 1" + bob <##. "receiving messages via" + bob <##. "sending messages via" + bob <## ("contact address: " <> cLink) + bob <## "connection not verified, use /code command to see security code" + bob <## currentChatVRangeInfo + +testMembershipProfileUpdateContactDeleted :: HasCallStack => FilePath -> IO () +testMembershipProfileUpdateContactDeleted = + testChat2 aliceProfile bobProfile $ + \alice bob -> do + createGroup2 "team" alice bob + + alice ##> "/contacts" + alice <## "bob (Bob)" + + alice #> "#team hello team" + bob <# "#team alice> hello team" + + alice ##> "/d bob" + alice <## "bob: contact is deleted" + bob <## "alice (Alice) deleted contact with you" + + alice ##> "/p alisa" + alice <## "user profile is changed to alisa (your 0 contacts are notified)" + + bob `hasContactProfiles` ["alice", "bob"] + + alice #> "#team team 1" + bob <## "contact alice changed to alisa" + bob <## "use @alisa <message> to send messages" + bob <# "#team alisa> team 1" + + bob `hasContactProfiles` ["alisa", "bob"] + + checkItems bob + + -- adding contact address to profile does not share it with member + alice ##> "/ad" + _ <- getContactLink alice True + alice ##> "/pa on" + alice <## "new contact address set" + + bob `hasContactProfiles` ["alisa", "bob"] + checkAliceNoProfileLink bob "alisa" + + alice #> "#team team 2" + bob <# "#team alisa> team 2" + + bob `hasContactProfiles` ["alisa", "bob"] + checkAliceNoProfileLink bob "alisa" + + -- profile update does not add contact address to member profile + alice ##> "/p 'Alice Smith'" + alice <## "user profile is changed to 'Alice Smith' (your 0 contacts are notified)" + + bob `hasContactProfiles` ["alisa", "bob"] + checkAliceNoProfileLink bob "alisa" + + alice #> "#team team 3" + bob <## "contact alisa changed to 'Alice Smith'" + bob <## "use @'Alice Smith' <message> to send messages" + bob <# "#team 'Alice Smith'> team 3" + + bob `hasContactProfiles` ["Alice Smith", "bob"] + checkAliceNoProfileLink bob "'Alice Smith'" + + checkItems bob + where + checkItems bob = do + bob ##> "/_get chat @2 count=100" + rCt <- chat <$> getTermLine bob + rCt `shouldNotContain` [(0, "updated profile")] + + bob ##> "/_get chat #1 count=100" + rGrp <- chat <$> getTermLine bob + rGrp `shouldContain` [(0, "updated profile")] + checkAliceNoProfileLink bob name = do + bob ##> ("/info #team " <> name) + bob <## "group ID: 1" + bob <## "member ID: 1" + bob <##. "receiving messages via" + bob <##. "sending messages via" + bob <## "connection not verified, use /code command to see security code" + bob <## currentChatVRangeInfo + +testMembershipProfileUpdateContactDisabled :: HasCallStack => FilePath -> IO () +testMembershipProfileUpdateContactDisabled = + testChat2 aliceProfile bobProfile $ + \alice bob -> do + createGroup2 "team" alice bob + + alice ##> "/contacts" + alice <## "bob (Bob)" + + alice #> "#team hello team" + bob <# "#team alice> hello team" + + alice ##> "/_delete @2 notify=off" + alice <## "bob: contact is deleted" + + alice ##> "/p alisa" + alice <## "user profile is changed to alisa (your 0 contacts are notified)" + + bob `hasContactProfiles` ["alice", "bob"] + + -- bob expects update from contact, so he doesn't update profile + alice #> "#team team 1" + bob <# "#team alice> team 1" + + bob `hasContactProfiles` ["alice", "bob"] + + -- bob sends any message to alice, increases auth err counter + bob `send` "/feed hi all" + bob <##. "/feed (1)" + bob <## "[alice, contactId: 2, connId: 1] error: connection authorization failed - this could happen if connection was deleted, secured with different credentials, or due to a bug - please re-create the connection" + + -- on next profile update from alice member, bob considers contact disabled for purposes of profile update + alice #> "#team team 2" + bob <# "#team alice> team 2" + + bob `hasContactProfiles` ["alice", "bob"] + + alice ##> "/p 'Alice Smith'" + alice <## "user profile is changed to 'Alice Smith' (your 0 contacts are notified)" + + alice #> "#team team 3" + bob <## "contact alice changed to 'Alice Smith'" + bob <## "use @'Alice Smith' <message> to send messages" + bob <# "#team 'Alice Smith'> team 3" + + bob `hasContactProfiles` ["Alice Smith", "bob"] + + bob ##> "/_get chat @2 count=100" + rCt <- chat <$> getTermLine bob + rCt `shouldNotContain` [(0, "updated profile")] + + bob ##> "/_get chat #1 count=100" + rGrp <- chat <$> getTermLine bob + rGrp `shouldContain` [(0, "updated profile")] + +testMembershipProfileUpdateNoChangeIgnored :: HasCallStack => FilePath -> IO () +testMembershipProfileUpdateNoChangeIgnored = + testChat2 aliceProfile bobProfile $ + \alice bob -> do + createGroup2 "team" alice bob + + alice ##> "/contacts" + alice <## "bob (Bob)" + + alice #> "#team hello team" + bob <# "#team alice> hello team" + + alice ##> "/d bob" + alice <## "bob: contact is deleted" + bob <## "alice (Alice) deleted contact with you" + + alice ##> "/p alisa" + alice <## "user profile is changed to alisa (your 0 contacts are notified)" + + bob `hasContactProfiles` ["alice", "bob"] + + alice ##> "/p alice Alice" + alice <## "user profile is changed to alice (Alice) (your 0 contacts are notified)" + + bob `hasContactProfiles` ["alice", "bob"] + + alice #> "#team team 1" + bob <# "#team alice> team 1" + + bob `hasContactProfiles` ["alice", "bob"] + + bob ##> "/_get chat @2 count=100" + rCt <- chat <$> getTermLine bob + rCt `shouldNotContain` [(0, "updated profile")] + + bob ##> "/_get chat #1 count=100" + rGrp <- chat <$> getTermLine bob + rGrp `shouldNotContain` [(0, "updated profile")] + +testMembershipProfileUpdateContactLinkIgnored :: HasCallStack => FilePath -> IO () +testMembershipProfileUpdateContactLinkIgnored = + testChat2 aliceProfile bobProfile $ + \alice bob -> do + createGroup2 "team" alice bob + + alice ##> "/contacts" + alice <## "bob (Bob)" + + alice #> "#team hello team" + bob <# "#team alice> hello team" + + alice ##> "/d bob" + alice <## "bob: contact is deleted" + bob <## "alice (Alice) deleted contact with you" + + alice ##> "/ad" + _ <- getContactLink alice True + alice ##> "/pa on" + alice <## "new contact address set" + + bob `hasContactProfiles` ["alice", "bob"] + + alice #> "#team team 1" + bob <# "#team alice> team 1" + + bob ##> "/_get chat @2 count=100" + rCt <- chat <$> getTermLine bob + rCt `shouldNotContain` [(0, "updated profile")] + + bob ##> "/_get chat #1 count=100" + rGrp <- chat <$> getTermLine bob + rGrp `shouldNotContain` [(0, "updated profile")] + + bob ##> "/info #team alice" + bob <## "group ID: 1" + bob <## "member ID: 1" + bob <##. "receiving messages via" + bob <##. "sending messages via" + bob <## "connection not verified, use /code command to see security code" + bob <## currentChatVRangeInfo + +testBlockForAllMarkedBlocked :: HasCallStack => FilePath -> IO () +testBlockForAllMarkedBlocked = + testChat3 aliceProfile bobProfile cathProfile $ + \alice bob cath -> do + createGroup3 "team" alice bob cath + + threadDelay 1000000 + + bob #> "#team 1" + [alice, cath] *<# "#team bob> 1" + + threadDelay 1000000 + + alice ##> "/block for all #team bob" + alice <## "#team: you blocked bob" + cath <## "#team: alice blocked bob" + bob <// 50000 + + alice ##> "/ms team" + alice + <### [ "alice (Alice): owner, you, created group", + "bob (Bob): admin, invited, connected, blocked by admin", + "cath (Catherine): admin, invited, connected" + ] + + cath ##> "/ms team" + cath + <### [ "cath (Catherine): admin, you, connected", + "alice (Alice): owner, host, connected", + "bob (Bob): admin, connected, blocked by admin" + ] + + bob ##> "/ms team" + bob + <### [ "bob (Bob): admin, you, connected", + "alice (Alice): owner, host, connected", + "cath (Catherine): admin, connected" + ] + + threadDelay 1000000 + + bob #> "#team 2" + alice <# "#team bob> 2 [blocked by admin] <muted>" + cath <# "#team bob> 2 [blocked by admin] <muted>" + + threadDelay 1000000 + + bob #> "#team 3" + alice <# "#team bob> 3 [blocked by admin] <muted>" + cath <# "#team bob> 3 [blocked by admin] <muted>" + + threadDelay 1000000 + + alice ##> "/unblock for all #team bob" + alice <## "#team: you unblocked bob" + cath <## "#team: alice unblocked bob" + bob <// 50000 + + threadDelay 1000000 + + bob #> "#team 4" + [alice, cath] *<# "#team bob> 4" + + alice + #$> ( "/_get chat #1 count=6", + chat, + [ (0, "1"), + (1, "blocked bob (Bob)"), + (0, "2 [blocked by admin]"), + (0, "3 [blocked by admin]"), + (1, "unblocked bob (Bob)"), + (0, "4") + ] + ) + cath + #$> ( "/_get chat #1 count=6", + chat, + [ (0, "1"), + (0, "blocked bob (Bob)"), + (0, "2 [blocked by admin]"), + (0, "3 [blocked by admin]"), + (0, "unblocked bob (Bob)"), + (0, "4") + ] + ) + bob #$> ("/_get chat #1 count=4", chat, [(1, "1"), (1, "2"), (1, "3"), (1, "4")]) + +testBlockForAllFullDelete :: HasCallStack => FilePath -> IO () +testBlockForAllFullDelete = + testChat3 aliceProfile bobProfile cathProfile $ + \alice bob cath -> do + createGroup3 "team" alice bob cath + + alice ##> "/set delete #team on" + alice <## "updated group preferences:" + alice <## "Full deletion: on" + concurrentlyN_ + [ do + bob <## "alice updated group #team:" + bob <## "updated group preferences:" + bob <## "Full deletion: on", + do + cath <## "alice updated group #team:" + cath <## "updated group preferences:" + cath <## "Full deletion: on" + ] + + threadDelay 1000000 + + bob #> "#team 1" + [alice, cath] *<# "#team bob> 1" + + threadDelay 1000000 + + alice ##> "/block for all #team bob" + alice <## "#team: you blocked bob" + cath <## "#team: alice blocked bob" + bob <// 50000 + + threadDelay 1000000 + + bob #> "#team 2" + alice <# "#team bob> blocked [blocked by admin] <muted>" + cath <# "#team bob> blocked [blocked by admin] <muted>" + + threadDelay 1000000 + + bob #> "#team 3" + alice <# "#team bob> blocked [blocked by admin] <muted>" + cath <# "#team bob> blocked [blocked by admin] <muted>" + + threadDelay 1000000 + + alice ##> "/unblock for all #team bob" + alice <## "#team: you unblocked bob" + cath <## "#team: alice unblocked bob" + bob <// 50000 + + threadDelay 1000000 + + bob #> "#team 4" + [alice, cath] *<# "#team bob> 4" + + alice + #$> ( "/_get chat #1 count=6", + chat, + [ (0, "1"), + (1, "blocked bob (Bob)"), + (0, "blocked [blocked by admin]"), + (0, "blocked [blocked by admin]"), + (1, "unblocked bob (Bob)"), + (0, "4") + ] + ) + cath + #$> ( "/_get chat #1 count=6", + chat, + [ (0, "1"), + (0, "blocked bob (Bob)"), + (0, "blocked [blocked by admin]"), + (0, "blocked [blocked by admin]"), + (0, "unblocked bob (Bob)"), + (0, "4") + ] + ) + bob #$> ("/_get chat #1 count=4", chat, [(1, "1"), (1, "2"), (1, "3"), (1, "4")]) + +testBlockForAllAnotherAdminUnblocks :: HasCallStack => FilePath -> IO () +testBlockForAllAnotherAdminUnblocks = + testChat3 aliceProfile bobProfile cathProfile $ + \alice bob cath -> do + createGroup3 "team" alice bob cath + + bob #> "#team 1" + [alice, cath] *<# "#team bob> 1" + + alice ##> "/block for all #team bob" + alice <## "#team: you blocked bob" + cath <## "#team: alice blocked bob" + bob <// 50000 + + bob #> "#team 2" + alice <# "#team bob> 2 [blocked by admin] <muted>" + cath <# "#team bob> 2 [blocked by admin] <muted>" + + cath ##> "/unblock for all #team bob" + cath <## "#team: you unblocked bob" + alice <## "#team: cath unblocked bob" + bob <// 50000 + + bob #> "#team 3" + [alice, cath] *<# "#team bob> 3" + + bob #$> ("/_get chat #1 count=3", chat, [(1, "1"), (1, "2"), (1, "3")]) + +testBlockForAllBeforeJoining :: HasCallStack => FilePath -> IO () +testBlockForAllBeforeJoining = + testChat4 aliceProfile bobProfile cathProfile danProfile $ + \alice bob cath dan -> do + createGroup3 "team" alice bob cath + + bob #> "#team 1" + [alice, cath] *<# "#team bob> 1" + + alice ##> "/block for all #team bob" + alice <## "#team: you blocked bob" + cath <## "#team: alice blocked bob" + bob <// 50000 + + bob #> "#team 2" + [alice, cath] *<# "#team bob> 2 [blocked by admin] <muted>" + + connectUsers alice dan + addMember "team" alice dan GRAdmin + dan ##> "/j team" + concurrentlyN_ + [ alice <## "#team: dan joined the group", + do + dan <## "#team: you joined the group" + dan + <### [ "#team: member bob (Bob) is connected", + "#team: member cath (Catherine) is connected" + ], + aliceAddedDan bob, + aliceAddedDan cath + ] + + threadDelay 1000000 + + bob #> "#team 3" + [alice, cath, dan] *<# "#team bob> 3 [blocked by admin] <muted>" + + threadDelay 1000000 + + bob #> "#team 4" + [alice, cath, dan] *<# "#team bob> 4 [blocked by admin] <muted>" + + threadDelay 1000000 + + alice ##> "/unblock for all #team bob" + alice <## "#team: you unblocked bob" + cath <## "#team: alice unblocked bob" + dan <## "#team: alice unblocked bob" + bob <// 50000 + + threadDelay 1000000 + + bob #> "#team 5" + [alice, cath, dan] *<# "#team bob> 5" + + dan ##> "/_get chat #1 count=100" + r <- chat <$> getTermLine dan + r `shouldContain` [(0, "3 [blocked by admin]"), (0, "4 [blocked by admin]"), (0, "unblocked bob (Bob)"), (0, "5")] + r `shouldNotContain` [(0, "1")] + r `shouldNotContain` [(0, "1 [blocked by admin]")] + r `shouldNotContain` [(0, "2")] + r `shouldNotContain` [(0, "2 [blocked by admin]")] + where + aliceAddedDan :: HasCallStack => TestCC -> IO () + aliceAddedDan cc = do + cc <## "#team: alice added dan (Daniel) to the group (connecting...)" + cc <## "#team: new member dan is connected" + +testBlockForAllCantRepeat :: HasCallStack => FilePath -> IO () +testBlockForAllCantRepeat = + testChat3 aliceProfile bobProfile cathProfile $ + \alice bob cath -> do + createGroup3 "team" alice bob cath + + alice ##> "/unblock for all #team bob" + alice <## "bad chat command: already unblocked" + + cath ##> "/unblock for all #team bob" + cath <## "bad chat command: already unblocked" + + bob #> "#team 1" + [alice, cath] *<# "#team bob> 1" + + alice ##> "/block for all #team bob" + alice <## "#team: you blocked bob" + cath <## "#team: alice blocked bob" + bob <// 50000 + + alice ##> "/block for all #team bob" + alice <## "bad chat command: already blocked" + + cath ##> "/block for all #team bob" + cath <## "bad chat command: already blocked" + + bob #> "#team 2" + alice <# "#team bob> 2 [blocked by admin] <muted>" + cath <# "#team bob> 2 [blocked by admin] <muted>" + + cath ##> "/unblock for all #team bob" + cath <## "#team: you unblocked bob" + alice <## "#team: cath unblocked bob" + bob <// 50000 + + alice ##> "/unblock for all #team bob" + alice <## "bad chat command: already unblocked" + + cath ##> "/unblock for all #team bob" + cath <## "bad chat command: already unblocked" + + bob #> "#team 3" + [alice, cath] *<# "#team bob> 3" + + bob #$> ("/_get chat #1 count=3", chat, [(1, "1"), (1, "2"), (1, "3")]) diff --git a/tests/ChatTests/Local.hs b/tests/ChatTests/Local.hs new file mode 100644 index 0000000000..1d0c540d76 --- /dev/null +++ b/tests/ChatTests/Local.hs @@ -0,0 +1,189 @@ +{-# LANGUAGE OverloadedStrings #-} +{-# LANGUAGE PostfixOperators #-} + +module ChatTests.Local where + +import ChatClient +import ChatTests.ChatList (getChats_) +import ChatTests.Utils +import Data.Time (getCurrentTime) +import Data.Time.Format.ISO8601 (iso8601Show) +import Simplex.Chat.Controller (ChatConfig (..), InlineFilesConfig (..), defaultInlineFilesConfig) +import System.Directory (copyFile, doesFileExist) +import System.FilePath ((</>)) +import Test.Hspec hiding (it) +import UnliftIO.Async (concurrently_) + +chatLocalChatsTests :: SpecWith FilePath +chatLocalChatsTests = do + describe "note folders" $ do + it "create folders, add notes, read, search" testNotes + it "switch users" testUserNotes + it "preview pagination for notes" testPreviewsPagination + it "chat pagination" testChatPagination + it "stores files" testFiles + it "deleting files does not interfere with other chat types" testOtherFiles + +testNotes :: FilePath -> IO () +testNotes tmp = withNewTestChat tmp "alice" aliceProfile $ \alice -> do + createCCNoteFolder alice + + alice ##> "/contacts" + -- not a contact + + alice /* "keep in mind" + alice ##> "/tail" + alice <# "* keep in mind" + alice ##> "/chats" + alice <# "* keep in mind" + alice ##> "/? keep" + alice <# "* keep in mind" + + alice #$> ("/_read chat *1 from=1 to=100", id, "ok") + alice ##> "/_unread chat *1 on" + alice <## "ok" + + alice ##> "/_delete item *1 1 internal" + alice <## "message deleted" + alice ##> "/tail" + alice ##> "/chats" + + alice /* "ahoy!" + alice ##> "/_update item *1 1 text Greetings." + alice ##> "/tail *" + alice <# "* Greetings." + +testUserNotes :: FilePath -> IO () +testUserNotes tmp = withNewTestChat tmp "alice" aliceProfile $ \alice -> do + createCCNoteFolder alice + + alice /* "keep in mind" + alice ##> "/tail" + alice <# "* keep in mind" + + alice ##> "/create user secret" + alice <## "user profile: secret" + alice <## "use /p <display name> to change it" + alice <## "(the updated profile will be sent to all your contacts)" + + alice ##> "/tail" + + alice ##> "/_delete item *1 1 internal" + alice <## "chat db error: SENoteFolderNotFound {noteFolderId = 1}" + +testPreviewsPagination :: FilePath -> IO () +testPreviewsPagination tmp = withNewTestChat tmp "alice" aliceProfile $ \alice -> do + createCCNoteFolder alice + + tsS <- iso8601Show <$> getCurrentTime + alice /* "first" + tsM <- iso8601Show <$> getCurrentTime + alice /* "last" + tsE <- iso8601Show <$> getCurrentTime + + -- there's only one folder that got updated after tsM and before tsE + getChats_ alice "count=3" [("*", "last")] + getChats_ alice ("after=" <> tsE <> " count=10") [] + getChats_ alice ("after=" <> tsS <> " count=10") [("*", "last")] + getChats_ alice ("before=" <> tsM <> " count=10") [] + getChats_ alice ("before=" <> tsE <> " count=10") [("*", "last")] + getChats_ alice ("before=" <> tsS <> " count=10") [] + +testChatPagination :: FilePath -> IO () +testChatPagination tmp = withNewTestChat tmp "alice" aliceProfile $ \alice -> do + createCCNoteFolder alice + + alice /* "hello world" + alice /* "memento mori" + alice /* "knock-knock" + alice /* "who's there?" + + alice #$> ("/_get chat *1 count=100", chat, [(1, "hello world"), (1, "memento mori"), (1, "knock-knock"), (1, "who's there?")]) + alice #$> ("/_get chat *1 count=1", chat, [(1, "who's there?")]) + alice #$> ("/_get chat *1 after=2 count=10", chat, [(1, "knock-knock"), (1, "who's there?")]) + alice #$> ("/_get chat *1 after=2 count=2", chat, [(1, "knock-knock"), (1, "who's there?")]) + alice #$> ("/_get chat *1 after=1 count=2", chat, [(1, "memento mori"), (1, "knock-knock")]) + alice #$> ("/_get chat *1 before=3 count=10", chat, [(1, "hello world"), (1, "memento mori")]) + alice #$> ("/_get chat *1 before=3 count=2", chat, [(1, "hello world"), (1, "memento mori")]) + alice #$> ("/_get chat *1 before=4 count=2", chat, [(1, "memento mori"), (1, "knock-knock")]) + + alice #$> ("/_get chat *1 count=10 search=k-k", chat, [(1, "knock-knock")]) + +testFiles :: FilePath -> IO () +testFiles tmp = withNewTestChat tmp "alice" aliceProfile $ \alice -> do + -- setup + createCCNoteFolder alice + let files = "./tests/tmp/app_files" + alice ##> ("/_files_folder " <> files) + alice <## "ok" + + -- ui-like upload + let source = "./tests/fixtures/test.jpg" + let stored = files </> "test.jpg" + copyFile source stored + alice ##> "/_create *1 json {\"filePath\": \"test.jpg\", \"msgContent\": {\"text\":\"hi myself\",\"type\":\"image\",\"image\":\"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAgAAAAIAQMAAAD+wSzIAAAABlBMVEX///+/v7+jQ3Y5AAAADklEQVQI12P4AIX8EAgALgAD/aNpbtEAAAAASUVORK5CYII=\"}}" + alice <# "* hi myself" + alice <# "* file 1 (test.jpg)" + + alice ##> "/tail" + alice <# "* hi myself" + alice <# "* file 1 (test.jpg)" + + alice ##> "/_get chat *1 count=100" + r <- chatF <$> getTermLine alice + r `shouldBe` [((1, "hi myself"), Just "test.jpg")] + + alice ##> "/fs 1" + alice <## "bad chat command: not supported for local files" + + alice ##> "/fc 1" + alice <## "chat db error: SELocalFileNoTransfer {fileId = 1}" + + -- one more file + let stored2 = files </> "another_test.jpg" + copyFile source stored2 + alice ##> "/_create *1 json {\"filePath\": \"another_test.jpg\", \"msgContent\": {\"text\":\"\",\"type\":\"image\",\"image\":\"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAgAAAAIAQMAAAD+wSzIAAAABlBMVEX///+/v7+jQ3Y5AAAADklEQVQI12P4AIX8EAgALgAD/aNpbtEAAAAASUVORK5CYII=\"}}" + alice <# "* file 2 (another_test.jpg)" + + alice ##> "/_delete item *1 2 internal" + alice <## "message deleted" + doesFileExist stored2 `shouldReturn` False + doesFileExist stored `shouldReturn` True + + alice ##> "/clear *" + alice ##> "/fs 1" + alice <## "chat db error: SEChatItemNotFoundByFileId {fileId = 1}" + alice ##> "/tail" + doesFileExist stored `shouldReturn` False + +testOtherFiles :: FilePath -> IO () +testOtherFiles = + testChatCfg2 cfg aliceProfile bobProfile $ \alice bob -> do + connectUsers alice bob + createCCNoteFolder bob + bob ##> "/_files_folder ./tests/tmp/" + bob <## "ok" + alice ##> "/_send @2 json {\"msgContent\":{\"type\":\"voice\", \"duration\":10, \"text\":\"\"}, \"filePath\":\"./tests/fixtures/test.jpg\"}" + alice <# "@bob voice message (00:10)" + alice <# "/f @bob ./tests/fixtures/test.jpg" + -- below is not shown in "sent" mode + -- alice <## "use /fc 1 to cancel sending" + bob <# "alice> voice message (00:10)" + bob <# "alice> sends file test.jpg (136.5 KiB / 139737 bytes)" + -- below is not shown in "sent" mode + -- bob <## "use /fr 1 [<dir>/ | <path>] to receive it" + bob <## "started receiving file 1 (test.jpg) from alice" + concurrently_ + (alice <## "completed sending file 1 (test.jpg) to bob") + (bob <## "completed receiving file 1 (test.jpg) from alice") + + bob /* "test" + bob ##> "/tail *" + bob <# "* test" + bob ##> "/clear *" + bob ##> "/tail *" + bob ##> "/fs 1" + bob <## "receiving file 1 (test.jpg) complete, path: test.jpg" + doesFileExist "./tests/tmp/test.jpg" `shouldReturn` True + where + cfg = testCfg {inlineFiles = defaultInlineFilesConfig {offerChunks = 100, sendChunks = 100, receiveChunks = 100}} diff --git a/tests/ChatTests/Profiles.hs b/tests/ChatTests/Profiles.hs index 6813a4cc72..80cdc34c76 100644 --- a/tests/ChatTests/Profiles.hs +++ b/tests/ChatTests/Profiles.hs @@ -16,7 +16,7 @@ import Simplex.Chat.Store.Shared (createContact) import Simplex.Chat.Types (ConnStatus (..), GroupMemberRole (..), Profile (..)) import Simplex.Messaging.Encoding.String (StrEncoding (..)) import System.Directory (copyFile, createDirectoryIfMissing) -import Test.Hspec +import Test.Hspec hiding (it) chatProfileTests :: SpecWith FilePath chatProfileTests = do @@ -67,6 +67,7 @@ chatProfileTests = do xit'' "enable timed messages with contact" testEnableTimedMessagesContact it "enable timed messages in group" testEnableTimedMessagesGroup xit'' "timed messages enabled globally, contact turns on" testTimedMessagesEnabledGlobally + it "update multiple user preferences for multiple contacts" testUpdateMultipleUserPrefs testUpdateProfile :: HasCallStack => FilePath -> IO () testUpdateProfile = @@ -1558,7 +1559,7 @@ testSetContactPrefs = testChat2 aliceProfile bobProfile $ alice <## "contact bob removed full name" alice <## "bob updated preferences for you:" alice <## "Voice messages: enabled (you allow: yes, contact allows: yes)" - alice #$> ("/_get chat @2 count=100", chat, startFeatures <> [(1, "Voice messages: enabled for contact"), (0, "voice message (00:10)"), (1, "Voice messages: off"), (0, "Voice messages: enabled")]) + alice #$> ("/_get chat @2 count=100", chat, startFeatures <> [(1, "Voice messages: enabled for contact"), (0, "voice message (00:10)"), (1, "Voice messages: off"), (0, "updated profile"), (0, "Voice messages: enabled")]) (alice </) bob ##> "/_set prefs @2 {}" bob <## "your preferences for alice did not change" @@ -1569,7 +1570,7 @@ testSetContactPrefs = testChat2 aliceProfile bobProfile $ alice ##> "/_set prefs @2 {\"voice\": {\"allow\": \"no\"}}" alice <## "you updated preferences for bob:" alice <## "Voice messages: off (you allow: no, contact allows: yes)" - alice #$> ("/_get chat @2 count=100", chat, startFeatures <> [(1, "Voice messages: enabled for contact"), (0, "voice message (00:10)"), (1, "Voice messages: off"), (0, "Voice messages: enabled"), (1, "Voice messages: off")]) + alice #$> ("/_get chat @2 count=100", chat, startFeatures <> [(1, "Voice messages: enabled for contact"), (0, "voice message (00:10)"), (1, "Voice messages: off"), (0, "updated profile"), (0, "Voice messages: enabled"), (1, "Voice messages: off")]) bob <## "alice updated preferences for you:" bob <## "Voice messages: off (you allow: default (yes), contact allows: no)" bob #$> ("/_get chat @2 count=100", chat, startFeatures <> [(0, "Voice messages: enabled for you"), (1, "voice message (00:10)"), (0, "Voice messages: off"), (1, "Voice messages: enabled"), (0, "Voice messages: off")]) @@ -1864,3 +1865,30 @@ testTimedMessagesEnabledGlobally = bob <## "timed message deleted: hey" alice #$> ("/_get chat @2 count=100", chat, chatFeatures <> [(0, "Disappearing messages: enabled (1 sec)")]) bob #$> ("/_get chat @2 count=100", chat, chatFeatures <> [(1, "Disappearing messages: enabled (1 sec)")]) + +testUpdateMultipleUserPrefs :: HasCallStack => FilePath -> IO () +testUpdateMultipleUserPrefs = testChat3 aliceProfile bobProfile cathProfile $ + \alice bob cath -> do + connectUsers alice bob + alice #> "@bob hi bob" + bob <# "alice> hi bob" + + connectUsers alice cath + alice #> "@cath hi cath" + cath <# "alice> hi cath" + + alice ##> "/_profile 1 {\"displayName\": \"alice\", \"fullName\": \"Alice\", \"preferences\": {\"fullDelete\": {\"allow\": \"always\"}, \"reactions\": {\"allow\": \"no\"}, \"receipts\": {\"allow\": \"yes\", \"activated\": true}}}" + alice <## "updated preferences:" + alice <## "Full deletion allowed: always" + alice <## "Message reactions allowed: no" + + bob <## "alice updated preferences for you:" + bob <## "Full deletion: enabled for you (you allow: default (no), contact allows: always)" + bob <## "Message reactions: off (you allow: default (yes), contact allows: no)" + + cath <## "alice updated preferences for you:" + cath <## "Full deletion: enabled for you (you allow: default (no), contact allows: always)" + cath <## "Message reactions: off (you allow: default (yes), contact allows: no)" + + alice #$> ("/_get chat @2 count=100", chat, chatFeatures <> [(1, "hi bob"), (1, "Full deletion: enabled for contact"), (1, "Message reactions: off")]) + alice #$> ("/_get chat @3 count=100", chat, chatFeatures <> [(1, "hi cath"), (1, "Full deletion: enabled for contact"), (1, "Message reactions: off")]) diff --git a/tests/ChatTests/Utils.hs b/tests/ChatTests/Utils.hs index 65fa3bc4c1..433bf46036 100644 --- a/tests/ChatTests/Utils.hs +++ b/tests/ChatTests/Utils.hs @@ -11,6 +11,7 @@ import Control.Concurrent (threadDelay) import Control.Concurrent.Async (concurrently_) import Control.Concurrent.STM import Control.Monad (unless, when) +import Control.Monad.Except (runExceptT) import qualified Data.ByteString.Char8 as B import Data.Char (isDigit) import Data.List (isPrefixOf, isSuffixOf) @@ -20,6 +21,7 @@ import qualified Data.Text as T import Database.SQLite.Simple (Only (..)) import Simplex.Chat.Controller (ChatConfig (..), ChatController (..), InlineFilesConfig (..), defaultInlineFilesConfig) import Simplex.Chat.Protocol +import Simplex.Chat.Store.NoteFolders (createNoteFolder) import Simplex.Chat.Store.Profiles (getUserContactProfiles) import Simplex.Chat.Types import Simplex.Chat.Types.Preferences @@ -33,7 +35,9 @@ import System.Environment (lookupEnv, withArgs) import System.FilePath ((</>)) import System.IO.Silently (capture_) import System.Info (os) -import Test.Hspec +import Test.Hspec hiding (it) +import qualified Test.Hspec as Hspec +import UnliftIO (timeout) defaultPrefs :: Maybe Preferences defaultPrefs = Just $ toChatPrefs defaultChatPrefs @@ -53,11 +57,17 @@ cathProfile = Profile {displayName = "cath", fullName = "Catherine", image = Not danProfile :: Profile danProfile = Profile {displayName = "dan", fullName = "Daniel", image = Nothing, contactLink = Nothing, preferences = defaultPrefs} -xit' :: (HasCallStack, Example a) => String -> a -> SpecWith (Arg a) +it :: HasCallStack => String -> (FilePath -> Expectation) -> SpecWith (Arg (FilePath -> Expectation)) +it name test = + Hspec.it name $ \tmp -> timeout t (test tmp) >>= maybe (error "test timed out") pure + where + t = 90 * 1000000 + +xit' :: HasCallStack => String -> (FilePath -> Expectation) -> SpecWith (Arg (FilePath -> Expectation)) xit' = if os == "linux" then xit else it xit'' :: (HasCallStack, Example a) => String -> a -> SpecWith (Arg a) -xit'' = ifCI xit it +xit'' = ifCI xit Hspec.it xdescribe'' :: HasCallStack => String -> SpecWith a -> SpecWith a xdescribe'' = ifCI xdescribe describe @@ -223,8 +233,8 @@ groupFeatures'' = ((0, "Full deletion: off"), Nothing, Nothing), ((0, "Message reactions: on"), Nothing, Nothing), ((0, "Voice messages: on"), Nothing, Nothing), - ((0, "Files and media: on"), Nothing, Nothing) - -- ((0, "Recent history: on"), Nothing, Nothing) + ((0, "Files and media: on"), Nothing, Nothing), + ((0, "Recent history: on"), Nothing, Nothing) ] itemId :: Int -> String @@ -287,6 +297,11 @@ cc <##.. ls = do unless prefix $ print ("expected to start from one of: " <> show ls, ", got: " <> l) prefix `shouldBe` True +(/*) :: HasCallStack => TestCC -> String -> IO () +cc /* note = do + cc `send` ("/* " <> note) + (dropTime <$> getTermLine cc) `shouldReturn` ("* " <> note) + data ConsoleResponse = ConsoleString String | WithTime String @@ -462,6 +477,12 @@ withCCTransaction :: TestCC -> (DB.Connection -> IO a) -> IO a withCCTransaction cc action = withTransaction (chatStore $ chatController cc) $ \db -> action db +createCCNoteFolder :: TestCC -> IO () +createCCNoteFolder cc = + withCCTransaction cc $ \db -> + withCCUser cc $ \user -> + runExceptT (createNoteFolder db user) >>= either (fail . show) pure + getProfilePictureByName :: TestCC -> String -> IO (Maybe String) getProfilePictureByName cc displayName = withTransaction (chatStore $ chatController cc) $ \db -> diff --git a/tests/MobileTests.hs b/tests/MobileTests.hs index a6231fa27e..0ed1b30f5d 100644 --- a/tests/MobileTests.hs +++ b/tests/MobileTests.hs @@ -16,11 +16,12 @@ import qualified Data.Aeson.TH as JQ import Data.ByteString (ByteString) import qualified Data.ByteString as B import qualified Data.ByteString.Char8 as BS -import Data.ByteString.Internal (create, memcpy) +import Data.ByteString.Internal (create) import qualified Data.ByteString.Lazy.Char8 as LB import Data.Word (Word8, Word32) import Foreign.C import Foreign.Marshal.Alloc (mallocBytes) +import Foreign.Marshal.Utils (copyBytes) import Foreign.Ptr import Foreign.StablePtr import Foreign.Storable (peek) @@ -42,7 +43,7 @@ import Simplex.Messaging.Parsers (dropPrefix, sumTypeJSON) import System.Directory (copyFile) import System.FilePath ((</>)) import System.IO (utf8) -import Test.Hspec +import Test.Hspec hiding (it) mobileTests :: HasCallStack => SpecWith FilePath mobileTests = do @@ -291,7 +292,7 @@ testFileCApi fileName tmp = do peek ptr' `shouldReturn` (0 :: Word8) sz :: Word32 <- peek (ptr' `plusPtr` 1) let sz' = fromIntegral sz - contents <- create sz' $ \toPtr -> memcpy toPtr (ptr' `plusPtr` 5) sz' + contents <- create sz' $ \toPtr -> copyBytes toPtr (ptr' `plusPtr` 5) sz' contents `shouldBe` src sz' `shouldBe` fromIntegral len diff --git a/tests/ProtocolTests.hs b/tests/ProtocolTests.hs index f848aed6bd..783f7fb344 100644 --- a/tests/ProtocolTests.hs +++ b/tests/ProtocolTests.hs @@ -129,7 +129,7 @@ decodeChatMessageTest = describe "Chat message encoding/decoding" $ do "{\"v\":\"1\",\"msgId\":\"AQIDBA==\",\"event\":\"x.msg.new\",\"params\":{\"content\":{\"text\":\"hello\",\"type\":\"text\"}}}" ##==## ChatMessage chatInitialVRange (Just $ SharedMsgId "\1\2\3\4") (XMsgNew (MCSimple (extMsgContent (MCText "hello") Nothing))) it "x.msg.new chat message with chat version range" $ - "{\"v\":\"1-5\",\"msgId\":\"AQIDBA==\",\"event\":\"x.msg.new\",\"params\":{\"content\":{\"text\":\"hello\",\"type\":\"text\"}}}" + "{\"v\":\"1-7\",\"msgId\":\"AQIDBA==\",\"event\":\"x.msg.new\",\"params\":{\"content\":{\"text\":\"hello\",\"type\":\"text\"}}}" ##==## ChatMessage supportedChatVRange (Just $ SharedMsgId "\1\2\3\4") (XMsgNew (MCSimple (extMsgContent (MCText "hello") Nothing))) it "x.msg.new quote" $ "{\"v\":\"1\",\"msgId\":\"AQIDBA==\",\"event\":\"x.msg.new\",\"params\":{\"content\":{\"text\":\"hello to you too\",\"type\":\"text\"},\"quote\":{\"content\":{\"text\":\"hello there!\",\"type\":\"text\"},\"msgRef\":{\"msgId\":\"BQYHCA==\",\"sent\":true,\"sentAt\":\"1970-01-01T00:00:01.000000001Z\"}}}}" @@ -239,14 +239,17 @@ decodeChatMessageTest = describe "Chat message encoding/decoding" $ do "{\"v\":\"1\",\"event\":\"x.grp.mem.new\",\"params\":{\"memberInfo\":{\"memberRole\":\"admin\",\"memberId\":\"AQIDBA==\",\"profile\":{\"fullName\":\"Alice\",\"displayName\":\"alice\",\"image\":\"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAgAAAAIAQMAAAD+wSzIAAAABlBMVEX///+/v7+jQ3Y5AAAADklEQVQI12P4AIX8EAgALgAD/aNpbtEAAAAASUVORK5CYII=\",\"preferences\":{\"reactions\":{\"allow\":\"yes\"},\"voice\":{\"allow\":\"yes\"}}}}}}" #==# XGrpMemNew MemberInfo {memberId = MemberId "\1\2\3\4", memberRole = GRAdmin, v = Nothing, profile = testProfile} it "x.grp.mem.new with member chat version range" $ - "{\"v\":\"1\",\"event\":\"x.grp.mem.new\",\"params\":{\"memberInfo\":{\"memberRole\":\"admin\",\"memberId\":\"AQIDBA==\",\"v\":\"1-5\",\"profile\":{\"fullName\":\"Alice\",\"displayName\":\"alice\",\"image\":\"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAgAAAAIAQMAAAD+wSzIAAAABlBMVEX///+/v7+jQ3Y5AAAADklEQVQI12P4AIX8EAgALgAD/aNpbtEAAAAASUVORK5CYII=\",\"preferences\":{\"reactions\":{\"allow\":\"yes\"},\"voice\":{\"allow\":\"yes\"}}}}}}" + "{\"v\":\"1\",\"event\":\"x.grp.mem.new\",\"params\":{\"memberInfo\":{\"memberRole\":\"admin\",\"memberId\":\"AQIDBA==\",\"v\":\"1-7\",\"profile\":{\"fullName\":\"Alice\",\"displayName\":\"alice\",\"image\":\"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAgAAAAIAQMAAAD+wSzIAAAABlBMVEX///+/v7+jQ3Y5AAAADklEQVQI12P4AIX8EAgALgAD/aNpbtEAAAAASUVORK5CYII=\",\"preferences\":{\"reactions\":{\"allow\":\"yes\"},\"voice\":{\"allow\":\"yes\"}}}}}}" #==# XGrpMemNew MemberInfo {memberId = MemberId "\1\2\3\4", memberRole = GRAdmin, v = Just $ ChatVersionRange supportedChatVRange, profile = testProfile} it "x.grp.mem.intro" $ "{\"v\":\"1\",\"event\":\"x.grp.mem.intro\",\"params\":{\"memberInfo\":{\"memberRole\":\"admin\",\"memberId\":\"AQIDBA==\",\"profile\":{\"fullName\":\"Alice\",\"displayName\":\"alice\",\"image\":\"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAgAAAAIAQMAAAD+wSzIAAAABlBMVEX///+/v7+jQ3Y5AAAADklEQVQI12P4AIX8EAgALgAD/aNpbtEAAAAASUVORK5CYII=\",\"preferences\":{\"reactions\":{\"allow\":\"yes\"},\"voice\":{\"allow\":\"yes\"}}}}}}" - #==# XGrpMemIntro MemberInfo {memberId = MemberId "\1\2\3\4", memberRole = GRAdmin, v = Nothing, profile = testProfile} + #==# XGrpMemIntro MemberInfo {memberId = MemberId "\1\2\3\4", memberRole = GRAdmin, v = Nothing, profile = testProfile} Nothing it "x.grp.mem.intro with member chat version range" $ - "{\"v\":\"1\",\"event\":\"x.grp.mem.intro\",\"params\":{\"memberInfo\":{\"memberRole\":\"admin\",\"memberId\":\"AQIDBA==\",\"v\":\"1-5\",\"profile\":{\"fullName\":\"Alice\",\"displayName\":\"alice\",\"image\":\"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAgAAAAIAQMAAAD+wSzIAAAABlBMVEX///+/v7+jQ3Y5AAAADklEQVQI12P4AIX8EAgALgAD/aNpbtEAAAAASUVORK5CYII=\",\"preferences\":{\"reactions\":{\"allow\":\"yes\"},\"voice\":{\"allow\":\"yes\"}}}}}}" - #==# XGrpMemIntro MemberInfo {memberId = MemberId "\1\2\3\4", memberRole = GRAdmin, v = Just $ ChatVersionRange supportedChatVRange, profile = testProfile} + "{\"v\":\"1\",\"event\":\"x.grp.mem.intro\",\"params\":{\"memberInfo\":{\"memberRole\":\"admin\",\"memberId\":\"AQIDBA==\",\"v\":\"1-7\",\"profile\":{\"fullName\":\"Alice\",\"displayName\":\"alice\",\"image\":\"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAgAAAAIAQMAAAD+wSzIAAAABlBMVEX///+/v7+jQ3Y5AAAADklEQVQI12P4AIX8EAgALgAD/aNpbtEAAAAASUVORK5CYII=\",\"preferences\":{\"reactions\":{\"allow\":\"yes\"},\"voice\":{\"allow\":\"yes\"}}}}}}" + #==# XGrpMemIntro MemberInfo {memberId = MemberId "\1\2\3\4", memberRole = GRAdmin, v = Just $ ChatVersionRange supportedChatVRange, profile = testProfile} Nothing + it "x.grp.mem.intro with member restrictions" $ + "{\"v\":\"1\",\"event\":\"x.grp.mem.intro\",\"params\":{\"memberRestrictions\":{\"restriction\":\"blocked\"},\"memberInfo\":{\"memberRole\":\"admin\",\"memberId\":\"AQIDBA==\",\"profile\":{\"fullName\":\"Alice\",\"displayName\":\"alice\",\"image\":\"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAgAAAAIAQMAAAD+wSzIAAAABlBMVEX///+/v7+jQ3Y5AAAADklEQVQI12P4AIX8EAgALgAD/aNpbtEAAAAASUVORK5CYII=\",\"preferences\":{\"reactions\":{\"allow\":\"yes\"},\"voice\":{\"allow\":\"yes\"}}}}}}" + #==# XGrpMemIntro MemberInfo {memberId = MemberId "\1\2\3\4", memberRole = GRAdmin, v = Nothing, profile = testProfile} (Just MemberRestrictions {restriction = MRSBlocked}) it "x.grp.mem.inv" $ "{\"v\":\"1\",\"event\":\"x.grp.mem.inv\",\"params\":{\"memberId\":\"AQIDBA==\",\"memberIntro\":{\"directConnReq\":\"simplex:/invitation#/?v=1&smp=smp%3A%2F%2F1234-w%3D%3D%40smp.simplex.im%3A5223%2F3456-w%3D%3D%23%2F%3Fv%3D1-2%26dh%3DMCowBQYDK2VuAyEAjiswwI3O_NlS8Fk3HJUW870EY2bAwmttMBsvRB9eV3o%253D&e2e=v%3D1-2%26x3dh%3DMEIwBQYDK2VvAzkAmKuSYeQ_m0SixPDS8Wq8VBaTS1cW-Lp0n0h4Diu-kUpR-qXx4SDJ32YGEFoGFGSbGPry5Ychr6U%3D%2CMEIwBQYDK2VvAzkAmKuSYeQ_m0SixPDS8Wq8VBaTS1cW-Lp0n0h4Diu-kUpR-qXx4SDJ32YGEFoGFGSbGPry5Ychr6U%3D\",\"groupConnReq\":\"simplex:/invitation#/?v=1&smp=smp%3A%2F%2F1234-w%3D%3D%40smp.simplex.im%3A5223%2F3456-w%3D%3D%23%2F%3Fv%3D1-2%26dh%3DMCowBQYDK2VuAyEAjiswwI3O_NlS8Fk3HJUW870EY2bAwmttMBsvRB9eV3o%253D&e2e=v%3D1-2%26x3dh%3DMEIwBQYDK2VvAzkAmKuSYeQ_m0SixPDS8Wq8VBaTS1cW-Lp0n0h4Diu-kUpR-qXx4SDJ32YGEFoGFGSbGPry5Ychr6U%3D%2CMEIwBQYDK2VvAzkAmKuSYeQ_m0SixPDS8Wq8VBaTS1cW-Lp0n0h4Diu-kUpR-qXx4SDJ32YGEFoGFGSbGPry5Ychr6U%3D\"}}}" #==# XGrpMemInv (MemberId "\1\2\3\4") IntroInvitation {groupConnReq = testConnReq, directConnReq = Just testConnReq} @@ -257,7 +260,7 @@ decodeChatMessageTest = describe "Chat message encoding/decoding" $ do "{\"v\":\"1\",\"event\":\"x.grp.mem.fwd\",\"params\":{\"memberIntro\":{\"directConnReq\":\"simplex:/invitation#/?v=1&smp=smp%3A%2F%2F1234-w%3D%3D%40smp.simplex.im%3A5223%2F3456-w%3D%3D%23%2F%3Fv%3D1-2%26dh%3DMCowBQYDK2VuAyEAjiswwI3O_NlS8Fk3HJUW870EY2bAwmttMBsvRB9eV3o%253D&e2e=v%3D1-2%26x3dh%3DMEIwBQYDK2VvAzkAmKuSYeQ_m0SixPDS8Wq8VBaTS1cW-Lp0n0h4Diu-kUpR-qXx4SDJ32YGEFoGFGSbGPry5Ychr6U%3D%2CMEIwBQYDK2VvAzkAmKuSYeQ_m0SixPDS8Wq8VBaTS1cW-Lp0n0h4Diu-kUpR-qXx4SDJ32YGEFoGFGSbGPry5Ychr6U%3D\",\"groupConnReq\":\"simplex:/invitation#/?v=1&smp=smp%3A%2F%2F1234-w%3D%3D%40smp.simplex.im%3A5223%2F3456-w%3D%3D%23%2F%3Fv%3D1-2%26dh%3DMCowBQYDK2VuAyEAjiswwI3O_NlS8Fk3HJUW870EY2bAwmttMBsvRB9eV3o%253D&e2e=v%3D1-2%26x3dh%3DMEIwBQYDK2VvAzkAmKuSYeQ_m0SixPDS8Wq8VBaTS1cW-Lp0n0h4Diu-kUpR-qXx4SDJ32YGEFoGFGSbGPry5Ychr6U%3D%2CMEIwBQYDK2VvAzkAmKuSYeQ_m0SixPDS8Wq8VBaTS1cW-Lp0n0h4Diu-kUpR-qXx4SDJ32YGEFoGFGSbGPry5Ychr6U%3D\"},\"memberInfo\":{\"memberRole\":\"admin\",\"memberId\":\"AQIDBA==\",\"profile\":{\"fullName\":\"Alice\",\"displayName\":\"alice\",\"image\":\"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAgAAAAIAQMAAAD+wSzIAAAABlBMVEX///+/v7+jQ3Y5AAAADklEQVQI12P4AIX8EAgALgAD/aNpbtEAAAAASUVORK5CYII=\",\"preferences\":{\"reactions\":{\"allow\":\"yes\"},\"voice\":{\"allow\":\"yes\"}}}}}}" #==# XGrpMemFwd MemberInfo {memberId = MemberId "\1\2\3\4", memberRole = GRAdmin, v = Nothing, profile = testProfile} IntroInvitation {groupConnReq = testConnReq, directConnReq = Just testConnReq} it "x.grp.mem.fwd with member chat version range and w/t directConnReq" $ - "{\"v\":\"1\",\"event\":\"x.grp.mem.fwd\",\"params\":{\"memberIntro\":{\"groupConnReq\":\"simplex:/invitation#/?v=1&smp=smp%3A%2F%2F1234-w%3D%3D%40smp.simplex.im%3A5223%2F3456-w%3D%3D%23%2F%3Fv%3D1-2%26dh%3DMCowBQYDK2VuAyEAjiswwI3O_NlS8Fk3HJUW870EY2bAwmttMBsvRB9eV3o%253D&e2e=v%3D1-2%26x3dh%3DMEIwBQYDK2VvAzkAmKuSYeQ_m0SixPDS8Wq8VBaTS1cW-Lp0n0h4Diu-kUpR-qXx4SDJ32YGEFoGFGSbGPry5Ychr6U%3D%2CMEIwBQYDK2VvAzkAmKuSYeQ_m0SixPDS8Wq8VBaTS1cW-Lp0n0h4Diu-kUpR-qXx4SDJ32YGEFoGFGSbGPry5Ychr6U%3D\"},\"memberInfo\":{\"memberRole\":\"admin\",\"memberId\":\"AQIDBA==\",\"v\":\"1-5\",\"profile\":{\"fullName\":\"Alice\",\"displayName\":\"alice\",\"image\":\"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAgAAAAIAQMAAAD+wSzIAAAABlBMVEX///+/v7+jQ3Y5AAAADklEQVQI12P4AIX8EAgALgAD/aNpbtEAAAAASUVORK5CYII=\",\"preferences\":{\"reactions\":{\"allow\":\"yes\"},\"voice\":{\"allow\":\"yes\"}}}}}}" + "{\"v\":\"1\",\"event\":\"x.grp.mem.fwd\",\"params\":{\"memberIntro\":{\"groupConnReq\":\"simplex:/invitation#/?v=1&smp=smp%3A%2F%2F1234-w%3D%3D%40smp.simplex.im%3A5223%2F3456-w%3D%3D%23%2F%3Fv%3D1-2%26dh%3DMCowBQYDK2VuAyEAjiswwI3O_NlS8Fk3HJUW870EY2bAwmttMBsvRB9eV3o%253D&e2e=v%3D1-2%26x3dh%3DMEIwBQYDK2VvAzkAmKuSYeQ_m0SixPDS8Wq8VBaTS1cW-Lp0n0h4Diu-kUpR-qXx4SDJ32YGEFoGFGSbGPry5Ychr6U%3D%2CMEIwBQYDK2VvAzkAmKuSYeQ_m0SixPDS8Wq8VBaTS1cW-Lp0n0h4Diu-kUpR-qXx4SDJ32YGEFoGFGSbGPry5Ychr6U%3D\"},\"memberInfo\":{\"memberRole\":\"admin\",\"memberId\":\"AQIDBA==\",\"v\":\"1-7\",\"profile\":{\"fullName\":\"Alice\",\"displayName\":\"alice\",\"image\":\"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAgAAAAIAQMAAAD+wSzIAAAABlBMVEX///+/v7+jQ3Y5AAAADklEQVQI12P4AIX8EAgALgAD/aNpbtEAAAAASUVORK5CYII=\",\"preferences\":{\"reactions\":{\"allow\":\"yes\"},\"voice\":{\"allow\":\"yes\"}}}}}}" #==# XGrpMemFwd MemberInfo {memberId = MemberId "\1\2\3\4", memberRole = GRAdmin, v = Just $ ChatVersionRange supportedChatVRange, profile = testProfile} IntroInvitation {groupConnReq = testConnReq, directConnReq = Nothing} it "x.grp.mem.info" $ "{\"v\":\"1\",\"event\":\"x.grp.mem.info\",\"params\":{\"memberId\":\"AQIDBA==\",\"profile\":{\"fullName\":\"Alice\",\"displayName\":\"alice\",\"image\":\"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAgAAAAIAQMAAAD+wSzIAAAABlBMVEX///+/v7+jQ3Y5AAAADklEQVQI12P4AIX8EAgALgAD/aNpbtEAAAAASUVORK5CYII=\",\"preferences\":{\"reactions\":{\"allow\":\"yes\"},\"voice\":{\"allow\":\"yes\"}}}}}" diff --git a/tests/RemoteTests.hs b/tests/RemoteTests.hs index ff0e5cb2d1..25c3514e4a 100644 --- a/tests/RemoteTests.hs +++ b/tests/RemoteTests.hs @@ -21,7 +21,7 @@ import Simplex.Messaging.Crypto.File (CryptoFileArgs (..)) import Simplex.Messaging.Encoding.String (strEncode) import Simplex.Messaging.Util import System.FilePath ((</>)) -import Test.Hspec +import Test.Hspec hiding (it) import UnliftIO import UnliftIO.Concurrent import UnliftIO.Directory @@ -142,7 +142,7 @@ storedBindingsTest = testChat2 aliceProfile aliceDesktopProfile $ \mobile deskto mobile ##> "/set device name Mobile" mobile <## "ok" - desktop ##> "/start remote host new addr=127.0.0.1 iface=lo port=52230" + desktop ##> "/start remote host new addr=127.0.0.1 iface=\"lo\" port=52230" desktop <##. "new remote host started on 127.0.0.1:52230" -- TODO: show ip? desktop <## "Remote session invitation:" inv <- getTermLine desktop diff --git a/tests/Test.hs b/tests/Test.hs index 9a942c556b..cbe8b627ec 100644 --- a/tests/Test.hs +++ b/tests/Test.hs @@ -12,7 +12,7 @@ import MobileTests import ProtocolTests import RemoteTests import SchemaDump -import Test.Hspec +import Test.Hspec hiding (it) import UnliftIO.Temporary (withTempDirectory) import ValidNames import ViewTests diff --git a/website/langs/ar.json b/website/langs/ar.json index 73a0da295a..5986d59e89 100644 --- a/website/langs/ar.json +++ b/website/langs/ar.json @@ -8,8 +8,8 @@ "simplex-explained-tab-1-text": "1. تجربة المستخدم", "simplex-privacy": "خصوصية SimpleX", "simplex-explained-tab-3-text": "3. ما الذي تراة الخوادم", - "simplex-explained-tab-1-p-1": "يمكنك إنشاء جهات اتصال ومجموعات وإجراء محادثات ثنائية الاتجاه، كما هو الحال في أي برنامج مراسلة آخر.", - "simplex-explained-tab-3-p-2": "يمكن للمستخدمين زيادة تحسين خصوصية البيانات الوصفية باستخدام Tor للوصول إلى الخوادم، ومنع الارتباط بواسطة عنوان IP.", + "simplex-explained-tab-1-p-1": "يمكنك إنشاء جهات اتصال ومجموعات وإجراء مُحادثات ثنائية الاتجاه، كما هو الحال في أي برنامج مُراسلة آخر.", + "simplex-explained-tab-3-p-2": "يمكن للمستخدمين زيادة تحسين خصوصية البيانات الوصفية باستخدام تور للوصول إلى الخوادم، ومنع الارتباط بواسطة عنوان IP.", "chat-bot-example": "مثال بوت الدردشة", "smp-protocol": "بروتوكول SMP", "chat-protocol": "بروتوكول الدردشة", @@ -17,51 +17,51 @@ "terminal-cli": "طرفية CLI", "terms-and-privacy-policy": "الشروط وسياسة الخصوصية", "hero-header": "إعادة تعريف الخصوصية", - "hero-overlay-1-textlink": "لماذا تعتبر معرفات المستخدم ضارة بالخصوصية؟", + "hero-overlay-1-textlink": "لماذا تعتبر معرّفات المستخدم ضارة بالخصوصية؟", "hero-overlay-2-textlink": "كيف يعمل SimpleX؟", - "hero-overlay-2-title": "لماذا تعتبر معرفات المستخدم ضارة بالخصوصية؟", - "feature-2-title": "تشفير<br>الصور والفيديوهات والملفات بين الطرفين", - "feature-3-title": "مجموعات لامركزية مشفرة — المستخدمون فقط يعرفون بوجودها", - "feature-5-title": "محادثات سرية اختفائية", - "feature-6-title": "تشفير المكالمات الصوتية والفيديو <br> بين الطرفين", - "simplex-network-overlay-1-title": "مقارنة مع بروتوكولات المراسلة P2P", - "simplex-private-4-title": "وصول <br> اختياري عبر Tor", + "hero-overlay-2-title": "لماذا تعتبر معرّفات المستخدم ضارة بالخصوصية؟", + "feature-2-title": "تَعْمِيَة<br>الصور والفيديوهات والملفات بين الطرفين", + "feature-3-title": "المجموعات اللامركزية — المستخدمون فقط يعرفون بوجودها", + "feature-5-title": "رسائل ذاتية الاختفاء", + "feature-6-title": "تَعْمِيَة المكالمات الصوتية والفيديو <br> بين الطرفين", + "simplex-network-overlay-1-title": "مقارنة مع بروتوكولات المُراسلة P2P", + "simplex-private-4-title": "وصول <br> اختياري عبر تور", "simplex-explained-tab-2-text": "2. كيف يعمل", - "simplex-explained-tab-1-p-2": "كيف يمكن أن تعمل مع قوائم انتظار أحادية الاتجاه وبدون معرفات ملف تعريف المستخدم؟", - "simplex-explained-tab-2-p-1": "لكل اتصال، تستخدم قائمتي انتظار منفصلتين للمراسلة لإرسال واستقبال الرسائل عبر خوادم مختلفة.", - "simplex-explained-tab-2-p-2": "تقوم الخوادم بتمرير الرسائل في اتجاه واحد فقط، دون الحصول على الصورة الكاملة لمحادثات المستخدم أو اتصالاته.", + "simplex-explained-tab-1-p-2": "كيف يمكن أن تعمل مع قوائم انتظار أحادية الاتجاه وبدون معرّفات ملف تعريف المستخدم؟", + "simplex-explained-tab-2-p-1": "لكل اتصال، تستخدم قائمتي انتظار منفصلتين للمُراسلة لإرسال واستلام الرسائل عبر خوادم مختلفة.", + "simplex-explained-tab-2-p-2": "تقوم الخوادم بتمرير الرسائل في اتجاه واحد فقط، دون الحصول على الصورة الكاملة لمُحادثات المستخدم أو اتصالاته.", "simplex-explained-tab-3-p-1": "تحتوي الخوادم على بيانات اعتماد مجهولة منفصلة لكل قائمة انتظار، ولا تعرف المستخدمين الذين ينتمون إليهم.", "copyright-label": "مشروع مفتوح المصدر © SimpleX 2020-2023", "simplex-chat-protocol": "بروتوكول دردشة SimpleX", "developers": "المطورين", - "hero-subheader": "أول نظام مراسلة<br> بدون معرفات المستخدم", + "hero-subheader": "أول نظام مُراسلة<br> بدون معرّفات المستخدم", "hero-p-1": "تحتوي التطبيقات الأخرى على معرّفات مستخدم: Signal ،Matrix ،Session ،Briar ،Jami ،Cwtch وما إلى ذلك. <br> SimpleX ليس لديه، <strong> ولا حتى أرقام عشوائية.</strong><br> وهذا يحسن خصوصيتك بشكل جذري.", "features": "الميزات", - "hero-2-header": "قم بإجراء اتصال خاص", + "hero-2-header": "أجري اتصال خاص", "hero-overlay-1-title": "كيف يعمل SimpleX؟", "hero-2-header-desc": "يُظهر الفيديو كيفية اتصالك بصديقك عبر رمز الاستجابة السريعة لمرة واحدة (QR code)، شخصيًا أو عبر رابط فيديو. يمكنك أيضًا الاتصال من خلال مشاركة رابط الدعوة.", - "feature-1-title": "تشفير الرسائل بين الطرفين مع دعم ماركداون والتحرير", - "feature-4-title": "تشفير الرسائل الصوتية بين الطرفين", + "feature-1-title": "تَعْمِيَة الرسائل بين الطرفين مع دعم ماركداون والتعديل", + "feature-4-title": "تَعْمِيَة الرسائل الصوتية بين الطرفين", "privacy-matters-overlay-card-1-p-1": "تستخدم العديد من الشركات الكبيرة معلومات حول من تتصل به لتقدير دخلك، وبيع المنتجات التي لا تحتاجها حقًا، ولتحديد الأسعار.", - "feature-7-title": "تخزين التطبيقات المشفرة المحمولة — نقل ملف التعريف إلى جهاز آخر", + "feature-7-title": "تخزين بيانات التطبيق مُعمَّاة ومحمولة — نقل ملف التعريف إلى جهاز آخر", "feature-8-title": "وضع التخفي — <br> فريد من نوعه لـ SimpleX Chat", - "simplex-private-1-title": "طبقتان من <br> التشفير بين الطرفين", - "simplex-private-2-title": "طبقة إضافية من <br> تشفير الخادم", + "simplex-private-1-title": "طبقتان من <br> التَعْمِيَة بين الطرفين", + "simplex-private-2-title": "طبقة إضافية من <br> تَعْمِيَة الخادم", "simplex-private-3-title": "تأمين نقل <br> TLS المصدق عليه", "simplex-private-5-title": "طبقات متعددة من <br> حشوة المحتوى", "simplex-private-7-title": "التحقق <br> من سلامة الرسالة", "simplex-private-8-title": "خلط الرسائل <br> لتقليل من الارتباط", - "simplex-private-10-title": "معرفات مزدوجة مؤقتة مجهولة الهوية", + "simplex-private-10-title": "معرفات زوجية مجهولة مؤقتة", "simplex-private-card-3-point-1": "يتم استخدام TLS 1.2 / 1.3 مع خوارزميات قوية فقط لاتصالات الخادم والعميل.", "simplex-private-card-3-point-2": "تعمل بصمة الخادم وربط القناة على منع هجمات الوسيط (MITM) وإعادة التشغيل.", "simplex-private-card-3-point-3": "استئناف الاتصال معطل لمنع هجمات الجلسة.", - "simplex-private-card-4-point-1": "لحماية عنوان IP الخاص بك، يمكنك الوصول إلى الخوادم عبر Tor أو بعض شبكات تراكب النقل الأخرى.", - "simplex-private-card-5-point-1": "يستخدم SimpleX حشوة المحتوى لكل طبقة تشفير لإحباط هجمات حجم الرسالة.", + "simplex-private-card-4-point-1": "لحماية عنوان IP الخاص بك، يمكنك الوصول إلى الخوادم عبر تور أو بعض شبكات تراكب النقل الأخرى.", + "simplex-private-card-5-point-1": "يستخدم SimpleX حشوة المحتوى لكل طبقة تَعْمِيَة لإحباط هجمات حجم الرسالة.", "simplex-private-card-6-point-2": "لمنع ذلك، تقوم تطبيقات SimpleX بتمرير مفاتيح لمرة واحدة خارج النطاق، عند مشاركة عنوان كرابط أو رمز QR.", "simplex-private-card-8-point-1": "تعمل خوادم SimpleX كعقد مختلطة بزمن انتقال منخفض — الرسائل الواردة والصادرة لها ترتيب مختلف.", "simplex-private-card-9-point-1": "كل رسالة انتظار تمرر الرسائل في اتجاه واحد، بعناوين إرسال واستلام مختلفة.", "simplex-private-card-9-point-2": "إنه يقلل من نواقل الهجوم، مقارنة بوسطاء الرسائل التقليديين، والبيانات الوصفية المتاحة.", - "simplex-private-card-10-point-1": "يستخدم SimpleX معرفات مزدوجة مؤقتة مجهولة الهوية للعناوين وبيانات الاعتماد لكل جهة اتصال مستخدم أو عضو مجموعة.", + "simplex-private-card-10-point-1": "يستخدم SimpleX معرّفات مزدوجة مؤقتة مجهولة الهوية للعناوين وبيانات الاعتماد لكل جهة اتصال مستخدم أو عضو مجموعة.", "privacy-matters-1-title": "الإعلانات والتمييز السعري", "privacy-matters-1-overlay-1-title": "الخصوصية توفر لك المال", "privacy-matters-1-overlay-1-linkText": "الخصوصية توفر لك المال", @@ -72,13 +72,13 @@ "privacy-matters-3-overlay-1-linkText": "الخصوصية تحمي حريتك", "simplex-unique-1-title": "لديك خصوصية كاملة", "simplex-unique-1-overlay-1-title": "الخصوصية الكاملة لهويتك وملفك الشخصي وجهات الاتصال والبيانات الوصفية", - "simplex-unique-2-title": "أنت محمي <br> من البريد العشوائي وإساءة الاستخدام", + "simplex-unique-2-title": "أنت محمي <br> من رسائل الإزعاج وإساءة الاستخدام", "simplex-unique-3-title": "أنت تتحكم في بياناتك", "simplex-unique-3-overlay-1-title": "ملكية ومراقبة وأمان بياناتك", "simplex-unique-4-title": "أنت تمتلك شبكة SimpleX", "simplex-unique-4-overlay-1-title": "لامركزية بالكامل — يمتلك المستخدمون شبكة SimpleX", "hero-overlay-card-1-p-4": "هذا التصميم يمنع تسريب أي البيانات الوصفية للمستخدمين على مستوى التطبيق. لزيادة تحسين الخصوصية وحماية عنوان IP الخاص بك، يمكنك الاتصال بخوادم المراسلة عبر Tor.", - "hero-overlay-card-1-p-5": "الأجهزة العميلة فقط هي التي تخزن ملفات تعريف المستخدمين، جهات الاتصال والمجموعات؛ يتم إرسال الرسائل بتشفير ثنائي الطبقة من طرف إلى طرف.", + "hero-overlay-card-1-p-5": "الأجهزة العميلة فقط هي التي تخزن ملفات تعريف المستخدمين، جهات الاتصال والمجموعات؛ يتم إرسال الرسائل بتَعْمِيَة ثنائية الطبقة من طرف إلى طرف.", "hero-overlay-card-2-p-2": "يمكنهم بعد ذلك ربط هذه المعلومات بالشبكات الاجتماعية العامة الحالية، وتحديد بعض الهويات الحقيقية.", "simplex-network-overlay-card-1-li-3": "P2P لا يحل مشكلة <a href='https://en.wikipedia.org/wiki/Man-in-the-middle_attack'>هجوم الوسيط (MITM)</a>، ومعظم التطبيقات الحالية لا تستخدم خارج النطاق رسائل للتبادل الأولي للمفاتيح. يستخدم SimpleX رسائل خارج النطاق أو، في بعض الحالات، اتصالات آمنة وموثوق بها موجودة مسبقًا لتبادل المفاتيح الأولي.", "privacy-matters-overlay-card-1-p-3": "تستخدم بعض الشركات المالية والتأمين رسوماً بيانية اجتماعية لتحديد أسعار الفائدة وأقساط التأمين. عادةً ما تجعل الأشخاص ذوي الدخل المنخفض يدفعون أكثر — أو كما يسمى<a href='https://fairbydesign.com/povertypremium/' target='_blank'> \"علاوة الفقر\"</a>.", @@ -88,45 +88,45 @@ "privacy-matters-overlay-card-1-p-4": "تحمي منصة SimpleX خصوصية اتصالاتك بشكل أفضل من أي بديل آخر، مما يمنع تمامًا الرسم البياني الاجتماعي الخاص بك من أن يصبح متاحًا لأي شركات أو مؤسسات. حتى عندما يستخدم الأشخاص الخوادم التي توفرها SimpleX Chat، فإننا لا نعرف عدد المستخدمين أو اتصالاتهم.", "simplex-private-card-1-point-1": "بروتوكول السقاطة المزدوجة — <br> رسائل OTR مع السرية المستمرة واستعادة الاختراق.", "simplex-private-card-1-point-2": "NaCL cryptobox في كل قائمة انتظار لمنع ارتباط حركة مرور البيانات بين قوائم انتظار الرسائل في حالة اختراق TLS.", - "simplex-private-card-2-point-1": "طبقة إضافية من تشفير الخادم للتسليم إلى المستلم، لمنع الارتباط بين حركة مرور بيانات الخادم المستلمة والمرسلة في حالة اختراق TLS.", - "simplex-private-card-4-point-2": "لاستخدام SimpleX عبر Tor، يرجى تثبيت <a href=\"https://guardianproject.info/apps/org.torproject.android/\" target=\"_blank\"> تطبيق Orbot </a> وتمكين وكيل SOCKS5 (أو VPN <a href = \"https://apps.apple.com/us/app/orbot/id1609461599؟platform=iphone\" target = \"_ blank\"> على iOS </a>).", + "simplex-private-card-2-point-1": "طبقة إضافية من تَعْمِيَة الخادم للتسليم إلى المُستلم، لمنع الارتباط بين حركة مرور بيانات الخادم المُستلمة والمُرسلة في حالة اختراق TLS.", + "simplex-private-card-4-point-2": "لاستخدام SimpleX عبر تور، يُرجى تثبيت <a href=\"https://guardianproject.info/apps/org.torproject.android/\" target=\"_blank\"> تطبيق Orbot </a> وتمكّين وكيل SOCKS5 (أو VPN <a href=\"https://apps.apple.com/us/app/orbot/id1609461599?platform=iphone\" target=\"_blank\">على iOS </a>).", "simplex-private-card-5-point-2": "يجعل الرسائل ذات الأحجام المختلفة تبدو متشابهة للخوادم ومراقبي الشبكة.", "simplex-private-card-6-point-1": "العديد من منصات الاتصال عرضة لهجمات الوسيط (MITM) من قبل الخوادم أو موفري الشبكات.", "simplex-private-card-7-point-1": "لضمان سلامة الرسائل يتم ترقيمها بالتسلسل وتضمين تجزئة الرسالة السابقة.", - "simplex-private-card-7-point-2": "إذا تمت إضافة أي رسالة أو إزالتها أو تغييرها، فسيتم تنبيه المستلم.", - "simplex-private-card-10-point-2": "يسمح بتسليم الرسائل بدون معرفات ملف تعريف المستخدم، مما يوفر خصوصية بيانات وصفية أفضل من البدائل.", + "simplex-private-card-7-point-2": "إذا أُضيفت أي رسالة أو أُزيلت أو تغيّرت، فسيتم تنبيه المُستلم.", + "simplex-private-card-10-point-2": "يسمح بتسليم الرسائل بدون معرّفات ملف تعريف المستخدم، مما يوفر خصوصية للبيانات الوصفية أفضل من البدائل.", "privacy-matters-2-overlay-1-linkText": "تمنحك الخصوصية القوة", - "simplex-unique-2-overlay-1-title": "أفضل حماية من البريد العشوائي وإساءة الاستخدام", - "hero-overlay-card-1-p-3": "أنت تحدد الخادم (الخوادم) المراد استخدامه لتلقي الرسائل وجهات الاتصال الخاصة بك — الخوادم التي تستخدمها لإرسال الرسائل إليهم. من المرجح أن تستخدم كل محادثة خادمين مختلفين.", - "hero-overlay-card-1-p-1": "سأل العديد من المستخدمين: <em> إذا لم يكن لدى SimpleX معرفات مستخدم، فكيف يمكنها معرفة مكان تسليم الرسائل؟ </em>", - "hero-overlay-card-1-p-2": "لتوصيل الرسائل، بدلاً من معرفات المستخدم التي تستخدمها جميع المنصات الأخرى، يستخدم SimpleX معرفات مزدوجة مؤقتة مجهولة الهوية لقوائم انتظار الرسائل، مختلفة لكل اتصال من اتصالاتك — لا توجد معرفات مستخدم دائمة.", - "simplex-network-overlay-card-1-p-1": "بروتوكولات المراسلة والتطبيقات <a href='https://en.wikipedia.org/wiki/Peer-to-peer'> P2P </a> بها مشاكل مختلفة تجعلها أقل موثوقية من SimpleX وأكثر تعقيدًا في التحليل و عرضة لعدة أنواع من الهجمات.", + "simplex-unique-2-overlay-1-title": "أفضل حماية من رسائل الإزعاج وإساءة الاستخدام", + "hero-overlay-card-1-p-3": "أنت تحدد الخادم (الخوادم) المراد استخدامه لاستلام الرسائل وجهات الاتصال الخاصة بك — الخوادم التي تستخدمها لإرسال الرسائل إليهم. من المرجح أن تستخدم كل مُحادثة خادمين مختلفين.", + "hero-overlay-card-1-p-1": "سأل العديد من المستخدمين: <em> إذا لم يكن لدى SimpleX معرّفات مستخدم، فكيف يمكنها معرفة مكان تسليم الرسائل؟ </em>", + "hero-overlay-card-1-p-2": "لتوصيل الرسائل، بدلاً من معرفات المستخدم التي تستخدمها جميع المنصات الأخرى، يستخدم SimpleX معرّفات مزدوجة مؤقتة مجهولة الهوية لقوائم انتظار الرسائل، مختلفة لكل اتصال من اتصالاتك — لا توجد معرفات مستخدم دائمة.", + "simplex-network-overlay-card-1-p-1": "بروتوكولات المُراسلة والتطبيقات <a href='https://en.wikipedia.org/wiki/Peer-to-peer'> P2P </a> بها مشاكل مختلفة تجعلها أقل موثوقية من SimpleX وأكثر تعقيدًا في التحليل و عرضة لعدة أنواع من الهجمات.", "hero-overlay-card-2-p-1": "عندما يكون لدى المستخدمين هويات ثابتة، حتى لو كان هذا مجرد رقم عشوائي، مثل معرف الجلسة، فهناك خطر يتمثل في أن الموفر أو المهاجم يمكنه مراقبة كيفية اتصال المستخدمين وعدد الرسائل التي يرسلونها.", "hero-overlay-card-1-p-6": "اقرأ المزيد في <a href='https://github.com/simplex-chat/simplexmq/blob/stable/protocol/overview-tjr.md' target='_blank'> SimpleX whitepaper </a>.", "hero-overlay-card-2-p-3": "حتى مع معظم التطبيقات الخاصة التي تستخدم خدمات Tor v3، إذا تحدثت إلى جهتي اتصال مختلفتين عبر نفس الملف الشخصي، فيمكنهما إثبات أنهما متصلان بنفس الشخص.", - "hero-overlay-card-2-p-4": "يحمي SimpleX من هذه الهجمات من خلال عدم وجود أي معرفات مستخدم في تصميمه. وإذا كنت تستخدم وضع التخفي، فسيكون لديك اسم عرض مختلف لكل جهة اتصال، مع تجنب أي بيانات مشتركة بينهما.", - "simplex-network-overlay-card-1-li-6": "قد تكون شبكات P2P عرضة <a href='https://www.usenix.org/conference/woot15/workshop-program/presentation/p2p-file-sharing-hell-exploiting-bittorrent'> هجوم DRDoS</a>، عندما يتمكن العملاء من إعادة بث حركة مرور البيانات وتضخيمها، مما يؤدي إلى رفض الخدمة على مستوى الشبكة. يقوم عملاء SimpleX فقط بترحيل حركة مرور البيانات من اتصال معروف ولا يمكن للمهاجم استخدامها لتضخيم حركة مرور البيانات في الشبكة بالكامل.", - "simplex-network-overlay-card-1-li-1": "تعتمد شبكات P2P على بعض المتغيرات من <a href='https://en.wikipedia.org/wiki/Distributed_hash_table'> DHT </a> لتوجيه الرسائل. يجب أن توازن تصميمات DHT بين ضمان التسليم وزمن الوصول. تتمتع SimpleX بضمان تسليم أفضل وزمن انتقال أقل من P2P، لأنه يمكن تمرير الرسالة بشكل متكرر عبر عدة خوادم بالتوازي، باستخدام الخوادم التي اختارها المستلم. في شبكات P2P، يتم تمرير الرسالة عبر عُقد <em> O (log N) </em> بالتسلسل، باستخدام العقد التي تختارها الخوارزمية.", + "hero-overlay-card-2-p-4": "يحمي SimpleX من هذه الهجمات من خلال عدم وجود أي معرّفات مستخدم في تصميمه. وإذا كنت تستخدم وضع التخفي، فسيكون لديك اسم عرض مختلف لكل جهة اتصال، مع تجنب أي بيانات مشتركة بينهما.", + "simplex-network-overlay-card-1-li-6": "قد تكون شبكات P2P عرضة <a href='https://www.usenix.org/conference/woot15/workshop-program/presentation/p2p-file-sharing-hell-exploiting-bittorrent'> هجوم DRDoS</a>، عندما يتمكّن العملاء من إعادة بث حركة مرور البيانات وتضخيمها، مما يؤدي إلى رفض الخدمة على مستوى الشبكة. يقوم عملاء SimpleX فقط بترحيل حركة مرور البيانات من اتصال معروف ولا يمكن للمهاجم استخدامها لتضخيم حركة مرور البيانات في الشبكة بالكامل.", + "simplex-network-overlay-card-1-li-1": "تعتمد شبكات P2P على بعض المتغيرات من <a href='https://en.wikipedia.org/wiki/Distributed_hash_table'> DHT </a> لتوجيه الرسائل. يجب أن توازن تصميمات DHT بين ضمان التسليم وزمن الوصول. تتمتع SimpleX بضمان تسليم أفضل وزمن انتقال أقل من P2P، لأنه يمكّن تمرير الرسالة بشكل متكرر عبر عدة خوادم بالتوازي، باستخدام الخوادم التي اختارها المُستلم. في شبكات P2P، يتم تمرير الرسالة عبر عُقد <em> O (log N) </em> بالتسلسل، باستخدام العُقد التي تختارها الخوارزمية.", "simplex-network-overlay-card-1-li-2": "لا يحتوي تصميم SimpleX، عكس معظم شبكات P2P، على معرّفات مستخدم عالمية من أي نوع، حتى مؤقتة، ويستخدم فقط المعرّفات المزدوجة المؤقتة، مما يوفر إخفاء هوية أفضل وحماية للبيانات الوصفية.", "simplex-network-overlay-card-1-li-4": "يمكن لبعض مزودي خدمة الإنترنت حظر تطبيقات P2P (مثل <a href='https://en.wikipedia.org/wiki/BitTorrent'> BitTorrent </a>). SimpleX حيادي النقل - يمكنه العمل عبر بروتوكولات الويب القياسية، على سبيل المثال WebSockets.", "simplex-network-overlay-card-1-li-5": "قد تكون جميع شبكات P2P المعروفة عرضة <a href='https://en.wikipedia.org/wiki/Sybil_attack'> لهجوم Sybil</a>، لأن كل عقدة قابلة للاكتشاف، وتعمل الشبكة ككل. تتطلب الإجراءات المعروفة لتخفيفها إما مكونًا مركزيًا أو <a href='https://en.wikipedia.org/wiki/Proof_of_work'> إثبات عمل مكلف </a>. لا تحتوي شبكة SimpleX على إمكانية اكتشاف الخادم، فهي مجزأة وتعمل كشبكات فرعية متعددة ومعزولة، مما يجعل الهجمات على مستوى الشبكة مستحيلة.", - "privacy-matters-overlay-card-3-p-1": "يجب على الجميع الاهتمام بخصوصية وأمان اتصالاتهم — يمكن للمحادثات غير الضارة أن تعرضك للخطر، حتى لو لم يكن لديك ما تخفيه.", - "privacy-matters-overlay-card-3-p-4": "لا يكفي استخدام برنامج مراسلة مشفر من طرف إلى طرف، يجب علينا جميعًا استخدام برامج المراسلة التي تحمي خصوصية شبكاتنا الشخصية — مع من نحن مرتبطون.", - "simplex-unique-overlay-card-1-p-3": "يحمي هذا التصميم خصوصية الأشخاص الذين تتواصل معهم، ويخفيها عن خوادم منصة SimpleX ومن أي مراقبين. لإخفاء عنوان IP الخاص بك من الخوادم، يمكنك <strong> الاتصال بخوادم SimpleX عبر Tor</strong>.", + "privacy-matters-overlay-card-3-p-1": "يجب على الجميع الاهتمام بخصوصية وأمان اتصالاتهم — يمكن للمُحادثات غير الضارة أن تعرضك للخطر، حتى لو لم يكن لديك ما تخفيه.", + "privacy-matters-overlay-card-3-p-4": "لا يكفي استخدام برنامج مُراسلة مُعمَّاة من طرف إلى طرف، يجب علينا جميعًا استخدام برامج مُراسلة التي تحمي خصوصية شبكاتنا الشخصية — مع من نحن مرتبطون.", + "simplex-unique-overlay-card-1-p-3": "يحمي هذا التصميم خصوصية الأشخاص الذين تتواصل معهم، ويخفيها عن خوادم منصة SimpleX ومن أي مراقبين. لإخفاء عنوان IP الخاص بك من الخوادم، يمكنك <strong> الاتصال بخوادم SimpleX عبر تور</strong>.", "simplex-unique-overlay-card-2-p-1": "نظرًا لعدم وجود معرف لديك على نظام SimpleX، لا يمكن لأي شخص الاتصال بك ما لم تشارك عنوان مستخدم لمرة واحدة أو مؤقتًا، كرمز QR أو رابط.", - "simplex-unique-overlay-card-2-p-2": "حتى مع عنوان المستخدم الاختياري، بينما يمكن استخدامه لإرسال طلبات جهات اتصال غير مرغوب فيها، يمكنك تغييره أو حذفه بالكامل دون فقد أي من اتصالاتك.", - "simplex-unique-overlay-card-3-p-2": "يتم الاحتفاظ بالرسائل المشفرة من طرف إلى طرف مؤقتًا على خوادم ترحيل SimpleX حتى يتم استلامها، ثم يتم حذفها نهائيًا.", - "simplex-unique-overlay-card-3-p-4": "لا توجد معرفات أو نص مشفر مشترك بين حركة مرور بيانات الخادم المرسلة والمستلمة — ؛ إذا كان أي شخص يراقب ذلك، فلن يتمكن بسهولة من تحديد من يتواصل مع من، حتى لو تم اختراق TLS.", + "simplex-unique-overlay-card-2-p-2": "حتى مع عنوان المستخدم الاختياري، بينما يمكن استخدامه لإرسال طلبات جهات اتصال مزعجة، يمكنك تغييره أو حذفه بالكامل دون فقد أي من اتصالاتك.", + "simplex-unique-overlay-card-3-p-2": "يتم الاحتفاظ بالرسائل المُعمَّاة من طرف إلى طرف مؤقتًا على خوادم ترحيل SimpleX حتى يتم استلامها، ثُمَّ تُحذف نهائيًا.", + "simplex-unique-overlay-card-3-p-4": "لا توجد معرفّات أو نص مُعَمَّى مشترك بين حركة مرور بيانات الخادم المُرسلة والمُستلمة — ؛ إذا كان أي شخص يراقب ذلك، فلن يتمكّن بسهولة من تحديد من يتواصل مع من، حتى لو اختُرق TLS.", "simplex-unique-card-1-p-1": "يحمي SimpleX خصوصية ملف التعريف الخاص بك، جهات الاتصال والبيانات الوصفية، ويخفيه عن خوادم منصة SimpleX وأي مراقبين.", "privacy-matters-overlay-card-2-p-1": "منذ وقت ليس ببعيد، لاحظنا أن الانتخابات الرئيسية يتم التلاعب بها بواسطة <a href='https://en.wikipedia.org/wiki/Facebook–Cambridge_Analytica_data_scandal' target='_blank'> شركة استشارية ذات سمعة طيبة </a> التي استخدمت الرسوم البيانية الاجتماعية لتشويه نظرتنا للعالم الحقيقي والتلاعب بأصواتنا.", "privacy-matters-overlay-card-2-p-2": "لكي تكون موضوعيًا وتتخذ قرارات مستقلة، يجب أن تكون متحكمًا في مساحة المعلومات الخاصة بك. هذا ممكن فقط إذا كنت تستخدم منصة اتصالات خاصة لا يمكنها الوصول إلى الرسم البياني الاجتماعي الخاص بك.", - "privacy-matters-overlay-card-2-p-3": "SimpleX هو النظام الأساسي الأول الذي لا يحتوي على أي معرفات مستخدم صمّم ليكون خاصًا، وبهذه الطريقة تحمي مخطط اتصالاتك بشكل أفضل من أي بديل معروف.", + "privacy-matters-overlay-card-2-p-3": "SimpleX هو النظام الأساسي الأول الذي لا يحتوي على أي معرّفات مستخدم صمّم ليكون خاصًا، وبهذه الطريقة تحمي مخطط اتصالاتك بشكل أفضل من أي بديل معروف.", "privacy-matters-overlay-card-3-p-2": "واحدة من أكثر القصص إثارة للصدمة هي تجربة <a href='https://en.wikipedia.org/wiki/Mohamedou_Ould_Slahi' target='_blank'> محمدو ولد صلاحي </a> الموصوفة في مذكراته والموضحة في فيلم موريتاني. تم وضعه في معتقل غوانتانامو بدون محاكمة، وتعرض للتعذيب هناك لمدة 15 عامًا بعد مكالمة هاتفية مع قريبه في أفغانستان، للاشتباه في تورطه في هجمات 11 سبتمبر، على الرغم من أنه عاش في ألمانيا طوال السنوات العشر الماضية.", "privacy-matters-overlay-card-3-p-3": "يتم القبض على الأشخاص العاديين بسبب ما يشاركونه عبر الإنترنت، حتى عبر حساباتهم \"المجهولة\"، <a href='https://www.dailymail.co.uk/news/article-11282263/Moment-police-swoop-house-devout-catholic-mother-malicious-online-posts.html' target='_blank'>وحتى في البلدان الديمقراطية</a>.", - "simplex-unique-overlay-card-1-p-1": "على عكس أنظمة المراسلة الأخرى، <strong>لا يحتوي SimpleX على معرفات مخصصة للمستخدمين</strong>. لا يعتمد على أرقام الهواتف أو العناوين المستندة إلى النطاقات (مثل البريد الإلكتروني أو XMPP)، أسماء المستخدمين، المفاتيح العامة أو حتى الأرقام العشوائية لتحديد مستخدميها — لا نعرف عدد الأشخاص الذين يستخدمون خوادم SimpleX الخاصة بنا.", - "simplex-unique-overlay-card-1-p-2": "لتسليم الرسائل، يستخدم SimpleX <a href='https://csrc.nist.gov/glossary/term/Pairwise_Pseudonymous_Identifier'> العناوين المزدوجة المجهولة </a> لقوائم انتظار الرسائل أحادية الاتجاه، منفصلة عن الرسائل المستلمة والمرسلة، عادةً عبر خوادم مختلفة. إن استخدام SimpleX يشبه امتلاك <strong>بريد إلكتروني أو هاتف “مؤقت” مختلف لكل جهة اتصال</strong>، ولا توجد متاعب في إدارتها.", - "simplex-unique-overlay-card-3-p-1": "يخزن SimpleX Chat جميع بيانات المستخدم على أجهزة العميل فقط باستخدام <strong> تنسيق قاعدة بيانات محمولة مشفرة </strong> يمكن تصديرها ونقلها إلى أي جهاز مدعوم.", - "simplex-unique-overlay-card-3-p-3": "على عكس خوادم الشبكات الموحدة (البريد الإلكتروني أو XMPP أو Matrix)، لا تقوم خوادم SimpleX بتخزين حسابات المستخدمين، فهي تقوم فقط بترحيل الرسائل، مما يحمي خصوصية كلا الطرفين.", + "simplex-unique-overlay-card-1-p-1": "على عكس أنظمة المُراسلة الأخرى، <strong>لا يحتوي SimpleX على معرّفات مخصصة للمستخدمين</strong>. لا يعتمد على أرقام الهواتف أو العناوين المستندة إلى النطاقات (مثل البريد الإلكتروني أو XMPP)، أسماء المستخدمين، المفاتيح العامة أو حتى الأرقام العشوائية لتحديد مستخدميها — لا نعرف عدد الأشخاص الذين يستخدمون خوادم SimpleX الخاصة بنا.", + "simplex-unique-overlay-card-1-p-2": "لتسليم الرسائل، يستخدم SimpleX <a href='https://csrc.nist.gov/glossary/term/Pairwise_Pseudonymous_Identifier'> العناوين المزدوجة المجهولة </a> لقوائم انتظار الرسائل أحادية الاتجاه، منفصلة عن الرسائل المُستلمة والمُرسلة، عادةً عبر خوادم مختلفة. إن استخدام SimpleX يشبه امتلاك <strong>بريد إلكتروني أو هاتف “مؤقت” مختلف لكل جهة اتصال</strong>، ولا توجد متاعب في إدارتها.", + "simplex-unique-overlay-card-3-p-1": "يخزن SimpleX Chat جميع بيانات المستخدم على أجهزة العميل فقط باستخدام <strong> تنسيق قاعدة بيانات محمولة مُعمَّاة </strong> يمكّن تصديرها ونقلها إلى أي جهاز مدعوم.", + "simplex-unique-overlay-card-3-p-3": "على عكس خوادم الشبكات الاتحادية (البريد الإلكتروني أو XMPP أو Matrix)، لا تقوم خوادم SimpleX بتخزين حسابات المستخدمين، فهي تقوم فقط بترحيل الرسائل، مما يحمي خصوصية كلا الطرفين.", "simplex-unique-overlay-card-4-p-1": "يمكنك <strong> استخدام SimpleX مع الخوادم الخاصة بك </strong> والاستمرار في التواصل مع الأشخاص الذين يستخدمون الخوادم المهيأة مسبقًا التي نقدمها.", "simplex-unique-overlay-card-4-p-3": "إذا كنت تفكر في التطوير لمنصة SimpleX، على سبيل المثال، بوت الدردشة لمستخدمي تطبيق SimpleX، أو دمج مكتبة SimpleX Chat في تطبيقات الأجهزة المحمولة، من فضلك <a href='https://simplex.chat/contact#/?v=1&smp=smp%3A%2F%2FPQUV2eL0t7OStZOoAsPEV2QYWt4-xilbakvGUGOItUo%3D%40smp6.simplex.im%2FK1rslx-m5bpXVIdMZg9NLUZ_8JBm8xTt%23MCowBQYDK2VuAyEALDeVe-sG8mRY22LsXlPgiwTNs9dbiLrNuA7f3ZMAJ2w%3D' target='_blank'>تواصل معي</a> لأي نصيحة والدعم.", "donate-here-to-help-us": "تبرّع هنا لمساعدتنا", @@ -151,21 +151,21 @@ "no-private": "لا - خصوصي", "no-resilient": "لا - مرن", "no-decentralized": "لا - لامركزي", - "no-federated": "لا - فدرالي", + "no-federated": "لا - اتِحاديّ", "comparison-section-list-point-2": "العناوين تعتمد على الـDNS", "comparison-section-list-point-3": "المفتاح العام أو معرف آخر فريد وعام", "comparison-section-list-point-7": "شبكات P2P إما لديها سلطة مركزية أو أن الشبكة كلها يمكن عرضة للخطر", "see-here": "اقرأ هنا", "no-secure": "لا - آمن", "comparison-section-list-point-5": "لا يحمي خصوصية البيانات الوصفية للمستخدمين", - "comparison-section-list-point-6": "على الرغم من أن الـP2P موزعة، إلا أنها ليست فدرالية - يعملون كشبكة واحدة", + "comparison-section-list-point-6": "على الرغم من أن الـP2P موزعة، إلا أنها ليست اتِحاديَّة - يعملون كشبكة واحدة", "comparison-section-list-point-1": "عادة ما يكون مكوناً من رقم الهاتف، أو اسم المستخدم في بعض الأحيان", "comparison-section-list-point-4": "إذا خوادم المشغّل مُخترقة. تحقق من رمز الأمان في Signal وبعض التطبيقات الأخرى للتخفيف منه", - "simplex-unique-card-3-p-1": "يخزن SimpleX جميع بيانات المستخدم على الأجهزة العميلة<strong> بتنسيق قاعدة بيانات محمولة مشفرة — </strong>يمكن نقله إلى جهاز آخر.", - "simplex-unique-card-4-p-1": "شبكة SimpleX لا مركزية بالكامل ومستقلة عن أي عملة مشفرة أو أي منصة أخرى، بخلاف الإنترنت.", + "simplex-unique-card-3-p-1": "يخزن SimpleX جميع بيانات المستخدم على الأجهزة العميلة<strong> بتنسيق قاعدة بيانات محمولة مُعمَّاة — </strong>يمكّن نقله إلى جهاز آخر.", + "simplex-unique-card-4-p-1": "شبكة SimpleX لا مركزية بالكامل ومستقلة عن أي عملة مُعمَّاة أو أي منصة أخرى، بخلاف الإنترنت.", "simplex-unique-card-4-p-2": "يمكنك<strong> استخدام SimpleX مع خوادمك الخاصة </strong> أو مع الخوادم التي نوفرها — ولا يزال الاتصال ممكن بأي مستخدم.", "join": "انضم إلى", - "we-invite-you-to-join-the-conversation": "نحن ندعوك للانضمام إلى محادثة", + "we-invite-you-to-join-the-conversation": "نحن ندعوك للانضمام إلى المُحادثة", "join-the-REDDIT-community": "انضم إلى مجتمع REDDIT", "join-us-on-GitHub": "انضم إلينا على GitHub", "contact-hero-p-2": "لم تقم بتنزيل SimpleX Chat حتى الآن؟", @@ -183,27 +183,27 @@ "if-you-already-installed-simplex-chat-for-the-terminal": "إذا قمت بالفعل بتثبيت SimpleX Chat للوحدة الطرفية", "simplex-chat-for-the-terminal": "SimpleX Chat للوحدة الطرفية", "privacy-matters-section-header": "لماذا الخصوصية <span class='gradient-text'> مهمة</span>", - "privacy-matters-section-label": "تأكد من أن برنامج المراسلة الخاص بك لا يمكنه الوصول إلى بياناتك!", + "privacy-matters-section-label": "تأكّد من أن برنامج المُراسلة الخاص بك لا يمكنه الوصول إلى بياناتك!", "tap-to-close": "انقر للإغلاق", "simplex-network-section-header": "شبكة<span class='gradient-text'> SimpleX </span>", "simplex-network-1-header": "على عكس شبكات P2P", "simplex-network-3-header": "شبكة SimpleX", "protocol-1-text": "Signal، منصات كبيرة", "protocol-2-text": "XMPP ،Matrix", - "simplex-unique-card-1-p-2": "بخلاف أي نظام أساسي آخر للمراسلة، لا يحتوي SimpleX على معرّفات مخصصة للمستخدمين —<strong> ولا حتى أرقام عشوائية</strong>.", + "simplex-unique-card-1-p-2": "بخلاف أي نظام مُراسلة آخر، لا يحتوي SimpleX على معرّفات مخصصة للمستخدمين —<strong> ولا حتى أرقام عشوائية</strong>.", "simplex-unique-card-2-p-1": "نظرًا لعدم وجود معرف أو عنوان ثابت على منصة SimpleX، لا يمكن لأي شخص الاتصال بك ما لم تشارك عنوان مستخدم لمرة واحدة أو مؤقتًا، كرمز QR أو رابط.", - "simplex-unique-card-3-p-2": "يتم الاحتفاظ بالرسائل المشفرة من طرف إلى طرف مؤقتًا على خوادم ترحيل SimpleX حتى يتم استلامها، ثم يتم حذفها نهائيًا.", + "simplex-unique-card-3-p-2": "يتم الاحتفاظ بالرسائل المُعمَّاة من طرف إلى طرف مؤقتًا على خوادم ترحيل SimpleX حتى يتم استلامها، ثُمَّ تُحذف نهائيًا.", "tap-the-connect-button-in-the-app": "اضغط على زر<span class='text-active-blue'> \"اتصال\"</span> في التطبيق", "scan-the-qr-code-with-the-simplex-chat-app": "امسح رمز QR باستخدام تطبيق SimpleX Chat", "scan-the-qr-code-with-the-simplex-chat-app-description": "لا يتم إرسال المفاتيح العامة وعنوان قائمة انتظار الرسائل في هذا الارتباط عبر الشبكة عند عرض هذه الصفحة —<br> فهي موجودة في جزء التجزئة لعنوان URL للرابط.", "if-you-already-installed": "إذا قمت بالفعل بتثبيت", "copy-the-command-below-text": "انسخ الأمر الذي في الاسفل واستخدمه في الدردشة:", - "simplex-private-section-header": "ما الذي يجعل SimpleX<span class='gradient-text'> خاصًا </span>", + "simplex-private-section-header": "ما الذي يجعل SimpleX<span class='gradient-text'> خصوصيًّا</span>", "privacy-matters-section-subheader": "الحفاظ على خصوصية بياناتك الوصفية — <span class='text-active-blue'> مع من تتحدث</span> — يحميك من:", "simplex-network-1-overlay-linktext": "مشاكل شبكات P2P", - "simplex-network-section-desc": "يوفر Simplex Chat أفضل خصوصية من خلال الجمع بين مزايا P2P والشبكات الموحدة.", + "simplex-network-section-desc": "يوفر Simplex Chat أفضل خصوصية من خلال الجمع بين مزايا P2P والشبكات الاتحادية.", "simplex-network-1-desc": "يتم إرسال جميع الرسائل عبر الخوادم، مما يوفر خصوصية أفضل للبيانات الوصفية وتسليمًا موثوقًا للرسائل غير المتزامنة، مع تجنب الكثير", - "simplex-network-2-header": "على عكس الشبكات الفيدرالية", + "simplex-network-2-header": "على عكس الشبكات الاتحادية", "simplex-network-3-desc": "توفر الخوادم <span class='text-active-blue'> قوائم انتظار أحادية الاتجاه </span> لتوصيل المستخدمين، لكن ليس لديهم رؤية للرسم البياني لاتصال الشبكة — إلا للمستخدمين فقط.", "comparison-section-header": "مقارنة مع البروتوكولات الأخرى", "simplex-network-2-desc": "لا تقوم خوادم الترحيل SimpleX بتخزين ملفات تعريف المستخدمين وجهات الاتصال والرسائل التي تم تسليمها، ولا تتصل ببعضها البعض، ولا يوجد دليل خوادم.", @@ -216,7 +216,7 @@ "guide-dropdown-4": "ملفات تعريف الدردشة", "guide-dropdown-5": "إدارة البيانات", "guide-dropdown-6": "مكالمات الصوت والفيديو", - "guide-dropdown-7": "الخصوصية والأمن", + "guide-dropdown-7": "الخصوصية و الأمان", "guide-dropdown-8": "إعدادات التطبيق", "guide-dropdown-9": "إجراء اتصالات", "docs-dropdown-4": "استضافة خادم SMP", @@ -242,8 +242,8 @@ "stable-versions-built-by-f-droid-org": "الإصدارات الثابتة التي تم إنشاؤها بواسطة F-Droid.org", "releases-to-this-repo-are-done-1-2-days-later": "يتم إصدار الإصدارات إلى هذا المستودع بعد يوم أو يومين", "f-droid-page-simplex-chat-repo-section-text": "لإضافته إلى عميل F-Droid، <span class='hide-on-mobile'>امسح رمز QR أو</span> استخدم عنوان URL هذا:", - "f-droid-page-f-droid-org-repo-section-text": "مستودعات SimpleX Chat و F-Droid.org مبنية على مفاتيح مختلفة. للتبديل، يرجى <a href='/docs/guide/chat-profiles.html#move-your-chat-profiles-to-another-device'>تصدير</a> قاعدة بيانات الدردشة وإعادة تثبيت التطبيق.", - "comparison-section-list-point-4a": "مُرحلات SimpleX لا يمكنها أن تتنازل عن تشفير بين الطرفين. تحقق من رمز الأمان للتخفيف من الهجوم على القناة خارج النطاق", + "f-droid-page-f-droid-org-repo-section-text": "مستودعات SimpleX Chat و F-Droid.org مبنية على مفاتيح مختلفة. للتبديل، يُرجى <a href='/docs/guide/chat-profiles.html#move-your-chat-profiles-to-another-device'>تصدير</a> قاعدة بيانات الدردشة وإعادة تثبيت التطبيق.", + "comparison-section-list-point-4a": "مُرحلات SimpleX لا يمكنها أن تتنازل عن تَعْمِيَة بين الطرفين. تحقق من رمز الأمان للتخفيف من الهجوم على القناة خارج النطاق", "hero-overlay-3-title": "التقييم الأمني", "hero-overlay-card-3-p-2": "قامت Trail of Bits بمراجعة مكونات التشفير والشبكات الخاصة بمنصة SimpleX في نوفمبر 2022.", "hero-overlay-card-3-p-3": "اقرأ المزيد في <a href=\"/blog/20221108-simplex-chat-v4.2-security-audit-new-website.html\">الإعلان</a>.", diff --git a/website/langs/es.json b/website/langs/es.json index 7c418b7e25..9b116b4215 100644 --- a/website/langs/es.json +++ b/website/langs/es.json @@ -20,7 +20,7 @@ "hero-overlay-1-title": "¿Cómo funciona SimpleX?", "hero-overlay-2-title": "¿Por qué los ID de usuario son perjudiciales para la privacidad?", "feature-1-title": "Mensajes cifrados E2E con sintáxis markdown y edición", - "feature-3-title": "Grupos secretos descentralizados —<br>sólo los usuarios saben de su existencia", + "feature-3-title": "Grupos descentralizados cifrados E2E — sólo los usuarios conocen su existencia", "feature-6-title": "Llamadas y videollamadas con cifrado E2E", "simplex-network-overlay-1-title": "Comparativa con protocolos de mensajería P2P", "developers": "Desarrolladores", @@ -30,7 +30,7 @@ "simplex-explained-tab-3-p-1": "Para cada cola los servidores disponen de credenciales separadas y anónimas, por lo que desconocen a qué usuarios pertenecen.", "hero-p-1": "Las demás aplicaciones usan ID de usuario: Signal, Matrix, Session, Briar, Jami, Cwtch, etc.<br> SimpleX no los tiene, <strong>ni siquiera números aleatorios</strong>.<br> Esto mejora radicalmente su privacidad.", "hero-2-header-desc": "El video muestra cómo se conecta con sus amistades a través del código QR de un solo uso, en persona o a través de videollamada. También puede conectarse compartiendo un enlace de invitación.", - "feature-7-title": "Base de datos portable cifrada — transfiera su perfil a otro dispositivo", + "feature-7-title": "Almacenamiento portable y cifrado — podrá transferir su perfil a otro dispositivo", "simplex-private-card-4-point-2": "Para usar SimpleX a través de Tor, instala la aplicación <a href=\"https://guardianproject.info/apps/org.torproject.android/\" target=\"_blank\">Orbot</a> y activa el proxy SOCKS5 (o VPN <a href=\"https://apps.apple.com/us/app/orbot/id1609461599?platform=iphone\" target=\"_blank\">en iOS</a>).", "simplex-private-card-3-point-1": "Para las conexiones cliente servidor se usan exclusivamente el protocolo TLS 1.2/1.3 con algoritmos robustos.", "simplex-private-card-4-point-1": "Para proteger tu dirección IP puedes acceder a los servidores a través de la red Tor u otras redes de transporte superpuesto.", @@ -48,7 +48,7 @@ "chat-protocol": "Protocolo Chat", "terminal-cli": "Terminal CLI", "hero-subheader": "La primera aplicación de mensajería<br>sin ID de usuario", - "feature-2-title": "Cifrado E2E<br>de imágenes y archivos", + "feature-2-title": "Cifrado E2E<br>de imágenes, vídeos y archivos", "feature-8-title": "Modo incógnito —<br>exclusivo de SimpleX Chat", "simplex-private-1-title": "Doble capa de<br>cifrado de extremo a extremo", "simplex-private-2-title": "Capa de cifrado<br>adicional en el servidor", diff --git a/website/langs/it.json b/website/langs/it.json index 1f3ad7fdda..3dda11e9c2 100644 --- a/website/langs/it.json +++ b/website/langs/it.json @@ -54,7 +54,7 @@ "simplex-unique-4-title": "Possiedi la rete SimpleX", "simplex-unique-4-overlay-1-title": "Completamente decentralizzata — gli utenti possiedono la rete SimpleX", "hero-overlay-card-1-p-1": "Molti utenti hanno chiesto: <em>se SimpleX non ha identificatori utente, come può sapere dove recapitare i messaggi? </em>", - "hero-overlay-card-1-p-3": "Sei tu a definire quale/i server usare per ricevere i messaggi, i tuoi contatti — i server che usi per inviare loro i messaggi. È probabile che ogni conversazione utilizzi due server diversi.", + "hero-overlay-card-1-p-3": "Sei tu a definire quale/i server usare per ricevere i messaggi, i tuoi contatti i server che usi per inviare loro i messaggi. È probabile che ogni conversazione utilizzi due server diversi.", "hero-overlay-card-1-p-5": "Solo i dispositivi client conservano profili utente, contatti e gruppi; i messaggi vengono inviati con crittografia end-to-end a 2 livelli.", "hero-overlay-card-1-p-6": "Maggiori informazioni nel <a href='https://github.com/simplex-chat/simplexmq/blob/stable/protocol/overview-tjr.md' target='_blank'>libro bianco di SimpleX</a>.", "hero-overlay-card-2-p-2": "Potrebbero quindi correlare queste informazioni con i social network pubblici esistenti e determinare alcune identità reali.", diff --git a/website/langs/ja.json b/website/langs/ja.json index b2ac7ecbc0..967d6c27f3 100644 --- a/website/langs/ja.json +++ b/website/langs/ja.json @@ -243,5 +243,12 @@ "hero-overlay-card-1-p-3": "メッセージの受信に使用するサーバー、連絡先を定義します —メッセージを送信するために使用するサーバー。 すべての会話では 2 つの異なるサーバーが使用される可能性があります。", "simplex-unique-overlay-card-1-p-1": "他のメッセージング プラットフォームとは異なり、SimpleX には<strong>ユーザーに割り当てられる識別子がありません</strong>。 ユーザーを識別するために、電話番号、ドメインベースのアドレス (電子メールや XMPP など)、ユーザー名、公開キー、さらには乱数にも依存しません。 —我々もSimpleX サーバーを何人が使用しているかはわかりません。", "f-droid-page-f-droid-org-repo-section-text": "SimpleX Chat と F-Droid.org リポジトリは、異なるキーを使用してビルドに署名します。 切り替えるには、チャット データベースを<a href='/docs/guide/chat-profiles.html#move-your-chat-profiles-to-another-device'>エクスポート</a>し、アプリを再インストールしてください。", - "simplex-private-5-title": "何レイヤーもの<br>コンテンツパディング" -} + "simplex-private-5-title": "何レイヤーもの<br>コンテンツパディング", + "hero-overlay-card-3-p-1": "<a href=\"https://www.trailofbits.com/about/\">Trail of Bits</a>は、大手ハイテク企業、政府機関、主要なブロックチェーン・プロジェクトなどを顧客に持つ、セキュリティとテクノロジーの大手コンサルタント会社です。", + "hero-overlay-card-3-p-3": "詳しくは <a href=\"/blog/20221108-simplex-chat-v4.2-security-audit-new-website.html\">お知らせ</a>をご覧ください。", + "jobs": "チームに参加する", + "hero-overlay-3-textlink": "セキュリティ監査", + "hero-overlay-3-title": "セキュリティ監査", + "hero-overlay-card-3-p-2": "Trail of Bitsは2022年11月にSimpleXプラットフォームの暗号とネットワークのコンポーネントを検証しました。", + "docs-dropdown-9": "ダウンロード" +} \ No newline at end of file diff --git a/website/langs/uk.json b/website/langs/uk.json index 6a48cc5640..e71b7cef8d 100644 --- a/website/langs/uk.json +++ b/website/langs/uk.json @@ -2,245 +2,253 @@ "features": "Особливості", "simplex-explained-tab-3-text": "3. Що бачать сервери", "terms-and-privacy-policy": "Умови та політика конфіденційності", - "feature-4-title": "E2E-зашифровані голосові повідомлення", - "feature-5-title": "Зникаючі повідомлення", - "simplex-private-card-3-point-3": "Відновлення підключення вимкнено для запобігання атакам сеансів.", - "simplex-private-card-7-point-1": "Щоб гарантувати цілісність, повідомлення послідовно нумеруються і включають хеш попереднього повідомлення.", - "simplex-private-card-10-point-2": "Він дозволяє доставляти повідомлення без ідентифікаторів профілю користувача, забезпечуючи кращу конфіденційність метаданих, ніж альтернативи.", - "privacy-matters-2-overlay-1-linkText": "Конфіденційність дає вам силу", - "hero-overlay-card-1-p-5": "Тільки клієнтські пристрої зберігають профілі користувачів, контакти та групи; повідомлення надсилаються з двошаровим наскрізним шифруванням.", - "hero-overlay-card-2-p-1": "Коли користувачі мають постійні ідентифікатори, навіть якщо це просто випадкове число, наприклад, ідентифікатор сеансу, існує ризик, що провайдер або зловмисник може спостерігати, як користувачі підключаються і скільки повідомлень вони надсилають.", - "simplex-network-overlay-card-1-li-5": "Всі відомі P2P-мережі можуть бути вразливими до <a href='https://en.wikipedia.org/wiki/Sybil_attack'>атаки Sybil</a>, оскільки кожен вузол можна виявити, а мережа працює як єдине ціле. Відомі заходи для її пом'якшення вимагають або централізованого компоненту, або дорогого <a href='https://en.wikipedia.org/wiki/Proof_of_work'>доказу роботи</a>. Мережа SimpleX не має можливості виявлення серверів, вона фрагментована і працює як кілька ізольованих підмереж, що унеможливлює атаки на всю мережу.", - "simplex-network-overlay-card-1-li-6": "P2P-мережі можуть бути вразливими до <a href='https://www.usenix.org/conference/woot15/workshop-program/presentation/p2p-file-sharing-hell-exploiting-bittorrent'>DRDoS-атаки</a>, коли клієнти можуть повторно транслювати та збільшувати трафік, що призводить до відмови в обслуговуванні всієї мережі. Клієнти SimpleX лише ретранслюють трафік із відомого з’єднання, і зловмисники не можуть використовувати їх для посилення трафіку в усій мережі.", - "privacy-matters-overlay-card-1-p-2": "Інтернет-магазини знають, що люди з нижчими доходами більш схильні до термінових покупок, тому вони можуть встановлювати вищі ціни або скасовувати знижки.", - "privacy-matters-overlay-card-1-p-3": "Деякі фінансові та страхові компанії використовують соціальні графіки для визначення процентних ставок і премій. Це часто змушує людей з нижчими доходами платити більше —, він відомий як <a href='https://fairbydesign.com/povertypremium/' target='_blank'>' премія за бідність'</a>.", - "privacy-matters-overlay-card-1-p-4": "Платформа SimpleX захищає конфіденційність ваших з'єднань краще, ніж будь-яка інша альтернатива, повністю запобігаючи тому, щоб ваш соціальний графік став доступним будь-яким компаніям або організаціям. Навіть коли люди використовують сервери, надані SimpleX Chat, ми не знаємо кількість користувачів та їхніх з'єднань.", - "privacy-matters-overlay-card-2-p-1": "Не так давно ми стали свідками маніпуляцій на великих виборах з боку <a href='https://en.wikipedia.org/wiki/Facebook–Cambridge_Analytica_data_scandal' target='_blank'>авторитетної консалтингової компанії</a>, яка використовувала наші соціальні графіки, щоб спотворити наше уявлення про реальний світ і маніпулювати нашими голосами.", - "privacy-matters-overlay-card-2-p-2": "Щоб бути об'єктивним і приймати незалежні рішення, необхідно контролювати свій інформаційний простір. Це можливо лише за умови використання приватної комунікаційної платформи, яка не має доступу до вашого соціального профілю.", - "privacy-matters-overlay-card-2-p-3": "SimpleX - це перша платформа, яка не має жодних ідентифікаторів користувачів, таким чином захищаючи ваш граф зв'язків краще, ніж будь-яка інша відома альтернатива.", - "privacy-matters-overlay-card-3-p-1": "Кожен має дбати про конфіденційність і безпеку своїх комунікацій — нешкідливі розмови можуть наражати вас на небезпеку, навіть якщо вам нема чого приховувати.", - "privacy-matters-overlay-card-3-p-2": "Однією з найбільш шокуючих історій є досвід <a href='https://en.wikipedia.org/wiki/Mohamedou_Ould_Slahi' target='_blank'>Мохамеду Ульд Салахі</a>, описаний у його мемуарах та показаний у фільмі \"Мавританець\". Його без суду і слідства помістили в табір Гуантанамо і катували там протягом 15 років після телефонного дзвінка родичу в Афганістані за підозрою в причетності до терактів 11 вересня, хоча він жив у Німеччині протягом останніх 10 років.", - "privacy-matters-overlay-card-3-p-4": "Недостатньо використовувати наскрізний зашифрований месенджер, ми всі повинні використовувати месенджери, які захищають конфіденційність наших особистих мереж — тих, з ким ми пов'язані.", - "simplex-unique-overlay-card-1-p-1": "На відміну від інших платформ обміну повідомленнями, SimpleX не має <strong>ніяких ідентифікаторів, призначених користувачам</strong>. Він не покладається на телефонні номери, доменні адреси (наприклад, електронну пошту або XMPP), імена користувачів, відкриті ключі або навіть випадкові числа для ідентифікації своїх користувачів — ми не ' знаємо, скільки людей користуються нашими серверами SimpleX.", - "simplex-unique-overlay-card-3-p-3": "На відміну від серверів об'єднаних мереж (електронна пошта, XMPP або Matrix), сервери SimpleX не зберігають облікові записи користувачів, вони лише пересилають повідомлення, захищаючи конфіденційність обох сторін.", - "simplex-unique-card-3-p-2": "Наскрізні зашифровані повідомлення тимчасово зберігаються на релейних серверах SimpleX до моменту отримання, після чого вони назавжди видаляються.", - "simplex-unique-card-4-p-1": "Мережа SimpleX повністю децентралізована і не залежить від будь-якої криптовалюти або будь-якої іншої платформи, окрім Інтернету.", - "simplex-network-overlay-card-1-li-3": "P2P не вирішує <a href='https://en.wikipedia.org/wiki/Man-in-the-middle_attack'>атаки MITM</a> проблема, і більшість існуючих реалізацій не використовують позасмугові повідомлення для початкового обміну ключами. SimpleX використовує позасмугові повідомлення або, в деяких випадках, уже існуючі безпечні та надійні з’єднання для початкового обміну ключами.", - "simplex-network-overlay-card-1-li-4": "Реалізації P2P можуть бути заблоковані деякими інтернет-провайдерами (наприклад, <a href='https://en.wikipedia.org/wiki/BitTorrent'>BitTorrent</a>). SimpleX є транспортно-агностичним - він може працювати через стандартні веб-протоколи, наприклад, WebSockets.", - "simplex-unique-card-4-p-2": "Ви можете <strong>використовувати SimpleX з власними серверами</strong> або з серверами, наданими нами — і при цьому підключатися до будь-якого користувача.", - "contact-hero-p-1": "Відкриті ключі та адреса черги повідомлень у цьому посиланні НЕ передаються мережею при перегляді цієї сторінки — вони містяться в хеш-фрагменті URL-адреси посилання.", - "scan-qr-code-from-mobile-app": "Відскануйте QR-код з мобільного додатку", - "to-make-a-connection": "Щоб встановити зв'язок:", - "install-simplex-app": "Встановіть додаток SimpleX", + "feature-4-title": "Голосові повідомлення з шифруванням від кінця до кінця", + "feature-5-title": "Зникнення повідомлень", + "simplex-private-card-3-point-3": "Відновлення з'єднання вимкнено для запобігання атакам на сесію.", + "simplex-private-card-7-point-1": "Для гарантії цілісності повідомлення пронумеровані послідовно та містять хеш попереднього повідомлення.", + "simplex-private-card-10-point-2": "Це дозволяє доставляти повідомлення без ідентифікаторів профілю користувача та забезпечує кращу конфіденційність метаданих, ніж альтернативи.", + "privacy-matters-2-overlay-1-linkText": "Конфіденційність дає вам владу", + "hero-overlay-card-1-p-5": "Тільки пристрої клієнта зберігають профілі користувачів, контакти та групи; повідомлення відправляються із шифруванням від кінця до кінця з двома шарами.", + "hero-overlay-card-2-p-1": "Коли у користувачів є постійні ідентифікатори, навіть якщо це просто випадковий номер, як, наприклад, ідентифікатор сеансу, існує ризик того, що провайдер чи зловмисник може спостерігати, як користувачі підключені та скільки повідомлень вони відправляють.", + "simplex-network-overlay-card-1-li-5": "Всі відомі P2P-мережі можуть бути вразливими до атаки <a href='https://en.wikipedia.org/wiki/Sybil_attack'>Sybil</a>, оскільки кожен вузол є відкритим, і мережа працює як ціле. Відомі заходи для пом'якшення цієї атаки вимагають або централізованого компонента, або дорогого <a href='https://en.wikipedia.org/wiki/Proof_of_work'>доказу роботи</a>. Мережа SimpleX не має виявності сервера, вона роздроблена і працює як кілька ізольованих підмереж, що робить неможливими атаки на всю мережу.", + "simplex-network-overlay-card-1-li-6": "P2P-мережі можуть бути вразливими до атаки <a href='https://www.usenix.org/conference/woot15/workshop-program/presentation/p2p-file-sharing-hell-exploiting-bittorrent'>DRDoS</a>, коли клієнти можуть ребродкастити та збільшувати трафік, що призводить до відмови в обслуговуванні на рівні всієї мережі. Клієнти SimpleX лише пересилають трафік від відомого підключення і не можуть бути використані зловмисником для збільшення трафіку в усій мережі.", + "privacy-matters-overlay-card-1-p-2": "Інтернет-роздрібники знають, що люди з низьким доходом частіше роблять термінові покупки, тому вони можуть встановлювати вищі ціни або скасовувати знижки.", + "privacy-matters-overlay-card-1-p-3": "Деякі фінансові та страхові компанії використовують соціальні графи для визначення ставок та страхових премій. Це часто змушує людей з низькими доходами платити більше — це відомо як <a href='https://fairbydesign.com/povertypremium/' target='_blank'>'поширений преміум'</a>.", + "privacy-matters-overlay-card-1-p-4": "Платформа SimpleX захищає конфіденційність ваших з'єднань краще, ніж будь-яка альтернатива, повністю запобігаючи доступу вашого соціального графа будь-яким компаніям чи організаціям. Навіть коли люди використовують сервери, надані SimpleX Chat, ми не знаємо кількість користувачів чи їх зв'язки.", + "privacy-matters-overlay-card-2-p-1": "Не так давно ми спостерігали, як великі вибори маніпулювалися <a href='https://en.wikipedia.org/wiki/Facebook–Cambridge_Analytica_data_scandal' target='_blank'>поважною консалтинговою компанією</a>, яка використовувала наші соціальні графи для спотворення нашого уявлення про реальний світ та маніпулювання нашими голосами.", + "privacy-matters-overlay-card-2-p-2": "Щоб бути об'єктивним та приймати незалежні рішення, вам потрібно контролювати ваш інформаційний простір. Це можливо лише за умови використання приватної платформи для спілкування, яка не має доступу до вашого соціального графа.", + "privacy-matters-overlay-card-2-p-3": "SimpleX - це перша платформа, яка не має жодних ідентифікаторів користувачів за своїм дизайном, таким чином, захищаючи ваш графік з'єднань краще, ніж будь-яка відома альтернатива.", + "privacy-matters-overlay-card-3-p-1": "Кожен повинен турбуватися про конфіденційність та безпеку свого спілкування — безпечні розмови можуть поставити вас під загрозу, навіть якщо у вас немає чого приховувати.", + "privacy-matters-overlay-card-3-p-2": "Однією з найшокуючих історій є досвід <a href='https://en.wikipedia.org/wiki/Mohamedou_Ould_Slahi' target='_blank'>Мохамеду Ульд Слахі</a>, описаний в його мемуарах і показаний у фільмі \"Мавританець\". Його посадили в табір Гуантанамо без суду і мукили там 15 років після телефонного дзвінка йому родичеві в Афганістані, під підозрою в причетності до атак 11 вересня, навіть не дивлячись на те, що він проживав у Німеччині протягом попередніх 10 років.", + "privacy-matters-overlay-card-3-p-4": "Недостатньо використовувати зашифрований від кінця до кінця месенджер; ми всі повинні використовувати месенджери, які захищають конфіденційність наших особистих мереж — з ким ми з'єднані.", + "simplex-unique-overlay-card-1-p-1": "На відміну від інших платформ обміну повідомленнями, у SimpleX <strong>не присвоюються ідентифікатори користувачів</strong>. Він не покладається на номери телефонів, адреси на основі домену (наприклад, електронна пошта або XMPP), імена користувачів, публічні ключі або навіть випадкові номери для ідентифікації своїх користувачів — ми не знаємо, скільки людей використовує наші сервери SimpleX.", + "simplex-unique-overlay-card-3-p-3": "На відміну від федеративних мереж серверів (електронна пошта, XMPP або Matrix), сервери SimpleX не зберігають облікові записи користувачів, вони лише ретранслюють повідомлення, захищаючи приватність обох сторін.", + "simplex-unique-card-3-p-2": "Зашифровані повідомлення від кінця до кінця тимчасово зберігаються на ретрансляційних серверах SimpleX до їх отримання, після чого вони назавжди видаляються.", + "simplex-unique-card-4-p-1": "Мережа SimpleX є повністю децентралізованою та незалежною від будь-якої криптовалюти чи іншої платформи, крім Інтернету.", + "simplex-network-overlay-card-1-li-3": "P2P не вирішує проблему атаки <a href='https://en.wikipedia.org/wiki/Man-in-the-middle_attack'>MITM</a>, і більшість існуючих реалізацій не використовують поза каналом повідомлень для початкового обміну ключами. SimpleX використовує поза каналом повідомлень або, у деяких випадках, передбачені і безпечні з'єднання для початкового обміну ключами.", + "simplex-network-overlay-card-1-li-4": "Реалізації P2P можуть бути блоковані деякими інтернет-провайдерами (наприклад, <a href='https://en.wikipedia.org/wiki/BitTorrent'>BitTorrent</a>). SimpleX є транспортно-агностичним - він може працювати через стандартні веб-протоколи, наприклад, WebSockets.", + "simplex-unique-card-4-p-2": "Ви можете <strong>використовувати SimpleX з власними серверами</strong> або з серверами, які ми надаємо — і все одно підключатися до будь-якого користувача.", + "contact-hero-p-1": "Публічні ключі та адреса черги повідомлень в цьому посиланні НЕ відправляються по мережі під час перегляду цієї сторінки — вони містяться в хеш-фрагменті URL-посилання.", + "scan-qr-code-from-mobile-app": "Сканувати QR-код з мобільного додатка", + "to-make-a-connection": "Щоб здійснити підключення:", + "install-simplex-app": "Встановити додаток SimpleX", "github-repository": "Репозиторій GitHub", - "no-federated": "Ні - федеративний", - "comparison-section-list-point-1": "Зазвичай на основі номера телефону, в деяких випадках на основі імені користувача", - "comparison-section-list-point-2": "Адреси на основі DNS", - "comparison-section-list-point-3": "Відкритий ключ або інший глобально унікальний ідентифікатор", - "comparison-section-list-point-7": "Мережі P2P або мають центральний орган, або вся мережа може бути скомпрометована", + "no-federated": "Ні - федеративно", + "comparison-section-list-point-1": "Зазвичай базується на номері телефону, у деяких випадках на іменах користувачів", + "comparison-section-list-point-2": "Адреси, засновані на DNS", + "comparison-section-list-point-3": "Відкритий ключ чи який-небудь інший глобально унікальний ідентифікатор", + "comparison-section-list-point-7": "Мережі P2P мають або центральний орган управління, або всю мережу можна порушити", "see-here": "дивіться тут", "guide-dropdown-4": "Профілі чату", - "guide-dropdown-5": "Керування даними", - "guide-dropdown-6": "Аудіо і відео дзвінки", - "guide-dropdown-7": "Конфіденційність і безпека", - "guide-dropdown-8": "Налаштування програми", - "guide-dropdown-9": "Встановлення зв'язків", - "guide": "Путівник", + "guide-dropdown-5": "Управління даними", + "guide-dropdown-6": "Аудіо та відеовиклики", + "guide-dropdown-7": "Конфіденційність та безпека", + "guide-dropdown-8": "Налаштування додатка", + "guide-dropdown-9": "Створення підключень", + "guide": "Посібник", "docs-dropdown-1": "Платформа SimpleX", "docs-dropdown-2": "Доступ до файлів Android", "docs-dropdown-3": "Доступ до бази даних чату", - "docs-dropdown-4": "Хост SMP-сервер", - "docs-dropdown-5": "Хост XFTP-сервер", + "docs-dropdown-4": "Хостинг сервера SMP", + "docs-dropdown-5": "Хостинг сервера XFTP", "docs-dropdown-6": "Сервери WebRTC", - "docs-dropdown-7": "Перекласти чат SimpleX", - "newer-version-of-eng-msg": "Існує новіша версія цієї сторінки англійською мовою.", + "docs-dropdown-7": "Переклад SimpleX Chat", + "newer-version-of-eng-msg": "Є нова версія цієї сторінки англійською мовою.", "click-to-see": "Натисніть, щоб побачити", "menu": "Меню", "on-this-page": "На цій сторінці", - "back-to-top": "Повернутися до початку", + "back-to-top": "Повернутися наверх", "home": "Головна", "developers": "Розробники", "reference": "Посилання", "blog": "Блог", "why-simplex": "Чому SimpleX", - "simplex-privacy": "Конфіденційність SimpleX", + "simplex-privacy": "Приватність у SimpleX", "simplex-network": "Мережа SimpleX", - "simplex-explained": "Simplex пояснення", + "simplex-explained": "Пояснення SimpleX", "simplex-explained-tab-1-text": "1. Що відчувають користувачі", "simplex-explained-tab-2-text": "2. Як це працює", - "simplex-explained-tab-1-p-1": "Ви можете створювати контакти та групи, а також вести двосторонні розмови, як і в будь-якому іншому месенджері.", - "simplex-explained-tab-1-p-2": "Як він може працювати з односпрямованими чергами та без ідентифікаторів профілю користувача?", - "simplex-explained-tab-2-p-1": "Для кожного підключення використовуються дві окремі черги обміну повідомленнями для надсилання та отримання повідомлень через різні сервери.", - "simplex-explained-tab-2-p-2": "Сервери передають повідомлення лише в один бік, не маючи повної картини розмови або з'єднань користувача.", - "simplex-explained-tab-3-p-1": "Сервери мають окремі анонімні облікові дані для кожної черги і не знають, яким користувачам вони належать.", - "simplex-explained-tab-3-p-2": "Користувачі можуть ще більше підвищити конфіденційність метаданих, використовуючи Tor для доступу до серверів, запобігаючи кореляції за IP-адресою.", + "simplex-explained-tab-1-p-1": "Ви можете створювати контакти та групи і вести двосторонні розмови, як у будь-якому іншому месенджері.", + "simplex-explained-tab-1-p-2": "Як це може працювати з однобічними чергами та без ідентифікаторів профілю користувача?", + "simplex-explained-tab-2-p-1": "Для кожного з'єднання ви використовуєте дві окремі черги обміну повідомленнями для відправки та отримання повідомлень через різні сервери.", + "simplex-explained-tab-2-p-2": "Сервери передають повідомлення тільки в одному напрямку, не маючи повної картини розмови або підключень користувача.", + "simplex-explained-tab-3-p-1": "Сервери мають окремі анонімні облікові дані для кожної черги і не знають, які користувачі до них відносяться.", + "simplex-explained-tab-3-p-2": "Користувачі можуть додатково підвищити конфіденційність метаданих, використовуючи Tor для доступу до серверів, що запобігає кореляції за IP-адресою.", "chat-bot-example": "Приклад чат-бота", - "smp-protocol": "SMP протокол", + "smp-protocol": "Протокол SMP", "chat-protocol": "Протокол чату", - "donate": "Пожертвуйте", - "copyright-label": "© 2020-2023 SimpleX | Проект з відкритим вихідним кодом", + "donate": "Пожертвувати", + "copyright-label": "© 2020-2023 SimpleX | Проект з відкритим кодом", "simplex-chat-protocol": "Протокол чату SimpleX", "terminal-cli": "Термінал CLI", - "hero-header": "Конфіденційність переглянута", + "hero-header": "Приватність переосмислена", "hero-subheader": "Перший месенджер<br>без ідентифікаторів користувачів", - "hero-p-1": "Інші додатки мають ідентифікатори користувачів: Signal, Matrix, Session, Briar, Jami, Cwtch тощо. <br> SimpleX цього не робить, <strong>навіть випадкових чисел</strong>. <br> Це радикально покращує вашу конфіденційність.", - "hero-overlay-1-textlink": "Чому ідентифікатори користувачів шкодять конфіденційності?", + "hero-p-1": "У інших додатках є ідентифікатори користувачів: Signal, Matrix, Session, Briar, Jami, Cwtch, тощо.<br> У SimpleX немає жодних, <strong>навіть випадкових номерів</strong>.<br> Це радикально покращує вашу конфіденційність.", + "hero-overlay-1-textlink": "Чому ідентифікатори користувачів шкідливі для конфіденційності?", "hero-overlay-2-textlink": "Як працює SimpleX?", "hero-2-header": "Створіть приватне з'єднання", - "hero-2-header-desc": "У відео показано, як з'єднатися з другом за допомогою одноразового QR-коду, особисто або за допомогою відеозв'язку. Ви також можете підключитися, поділившись посиланням-запрошенням.", + "hero-2-header-desc": "У відео показано, як ви можете підключитися до свого друга за його одноразовим QR-кодом, особисто або через відеозв'язок. Ви також можете підключитися, поділившись посиланням на запрошення.", "hero-overlay-1-title": "Як працює SimpleX?", - "hero-overlay-2-title": "Чому ідентифікатори користувачів шкодять конфіденційності?", - "feature-1-title": "E2E-зашифровані повідомлення з розміткою і редагуванням", - "feature-2-title": "E2E-зашифровані<br>зображення та файли", - "feature-3-title": "Децентралізовані секретні групи —<br>лише користувачі знають про їх існування", - "feature-6-title": "E2E-шифрується<br>audio і відеодзвінки", - "feature-7-title": "Портативна зашифрована база даних — перенесіть свій профіль на інший пристрій", + "hero-overlay-2-title": "Чому ідентифікатори користувачів шкідливі для конфіденційності?", + "feature-1-title": "Повідомлення з шифруванням від кінця до кінця з можливістю використання Markdown та редагування", + "feature-2-title": "Зображення, відео та файли з шифруванням від кінця до кінця", + "feature-3-title": "Децентралізовані групи з шифруванням від кінця до кінця — тільки користувачі знають про їх існування", + "feature-6-title": "Дзвінки з шифруванням від кінця до кінця для аудіо та відео", + "feature-7-title": "Переносне зашифроване зберігання додатку — переміщуйте профіль на інший пристрій", "feature-8-title": "Режим інкогніто —<br>унікальний для SimpleX Chat", - "simplex-network-overlay-1-title": "Порівняння з протоколами обміну повідомленнями P2P", - "simplex-private-1-title": "2-рівневе наскрізне шифрування", + "simplex-network-overlay-1-title": "Порівняння з протоколами P2P-повідомлень", + "simplex-private-1-title": "2 рівні шифрування від кінця до кінця", "simplex-private-2-title": "Додатковий рівень<br>шифрування сервера", - "simplex-private-3-title": "Безпечне автентифіковане<br>транспортування TLS", - "simplex-private-4-title": "Додатковий<br>доступ через Tor", - "simplex-private-5-title": "Кілька шарів<br>заповнення вмісту", - "simplex-private-6-title": "Позадіапазонний<br>обмін ключами", + "simplex-private-3-title": "Безпечний аутентифікований<br>транспорт TLS", + "simplex-private-4-title": "Опційний<br>доступ через Tor", + "simplex-private-5-title": "Кілька рівнів<br>наповнення вмісту", + "simplex-private-6-title": "Позаканальний<br>обмін ключами", "simplex-private-7-title": "Перевірка<br>цілісності повідомлення", - "simplex-private-9-title": "Односпрямовані<br>черги повідомлень", + "simplex-private-9-title": "Однобічні<br>черги повідомлень", "simplex-private-8-title": "Змішування повідомлень<br>для зменшення кореляції", "simplex-private-10-title": "Тимчасові анонімні парні ідентифікатори", - "simplex-private-card-1-point-1": "Протокол double-ratchet —<br>OTR messaging з ідеальною конфіденційністю та відновленням зламів.", - "simplex-private-card-1-point-2": "Криптобокс NaCL у кожній черзі для запобігання кореляції трафіку між чергами повідомлень, якщо TLS скомпрометовано.", - "simplex-private-card-2-point-1": "Додатковий рівень серверного шифрування для доставки одержувачу, щоб запобігти кореляції між отриманим і відправленим серверним трафіком, якщо TLS скомпрометовано.", - "simplex-private-card-3-point-1": "Для клієнт-серверних з'єднань використовується тільки TLS 1.2/1.3 з сильними алгоритмами.", - "simplex-private-card-3-point-2": "Відбитки пальців сервера та прив'язка каналів запобігають MITM-атакам та повторному відтворенню.", - "simplex-private-card-4-point-1": "Щоб захистити свою IP-адресу, ви можете отримати доступ до серверів через Tor або іншу транспортну мережу.", - "simplex-private-card-4-point-2": "Щоб використовувати SimpleX через Tor, установіть <a href=\"https://guardianproject.info/apps/org.torproject.android/\" target=\"_blank\">програму Orbot</a> і ввімкніть проксі-сервер SOCKS5 (або VPN <a href=\"https://apps.apple.com/us/app/orbot/id1609461599?platform=iphone\" target=\"_blank\">на iOS</a>).", - "simplex-private-card-5-point-1": "SimpleX використовує заповнення вмісту для кожного рівня шифрування, щоб запобігти атакам на розмір повідомлення.", - "simplex-private-card-5-point-2": "Це дозволяє повідомленням різного розміру виглядати однаково для серверів і мережевих спостерігачів.", - "simplex-private-card-6-point-1": "Багато комунікаційних платформ вразливі до MITM-атак з боку серверів або мережевих провайдерів.", - "simplex-private-card-6-point-2": "Щоб запобігти цьому, програми SimpleX передають одноразові ключі поза смугою, коли ви надаєте адресу як посилання або QR-код.", - "simplex-private-card-7-point-2": "Якщо будь-яке повідомлення буде додано, видалено або змінено, одержувач отримає сповіщення.", - "simplex-private-card-8-point-1": "Сервери SimpleX працюють як вузли змішування з низькою затримкою - вхідні та вихідні повідомлення йдуть в різному порядку.", - "simplex-private-card-9-point-1": "Кожна черга повідомлень передає повідомлення в одному напрямку, з різними адресами відправлення та отримання.", - "simplex-private-card-9-point-2": "У порівнянні з традиційними брокерами повідомлень, він зменшує кількість векторів атак і доступних мета-даних.", - "simplex-private-card-10-point-1": "SimpleX використовує тимчасові анонімні попарні адреси та облікові дані для кожного контакту користувача або члена групи.", - "privacy-matters-1-title": "Реклама та цінова дискримінація", - "privacy-matters-1-overlay-1-title": "Конфіденційність економить ваші гроші", - "privacy-matters-1-overlay-1-linkText": "Конфіденційність економить ваші гроші", + "simplex-private-card-1-point-1": "Протокол подвійної рейки — OTR-повідомлення з ідеальною передачею секрету та відновленням злому.", + "simplex-private-card-1-point-2": "NaCL криптокоробка в кожній черзі для запобігання кореляції трафіку між чергами повідомлень у разі компрометації TLS.", + "simplex-private-card-2-point-1": "Додатковий рівень шифрування сервера для доставки отримувачу для запобігання кореляції між отриманим та відісланим трафіком сервера у разі компрометації TLS.", + "simplex-private-card-3-point-1": "Використовується лише TLS 1.2/1.3 із сильними алгоритмами для з'єднань клієнт-сервер.", + "simplex-private-card-3-point-2": "Відбиток сервера та зв'язування каналу запобігають MITM та атакам повтору.", + "simplex-private-card-4-point-1": "Для захисту вашої IP-адреси ви можете отримати доступ до серверів через Tor чи іншу транспортну оверлейну мережу.", + "simplex-private-card-4-point-2": "Для використання SimpleX через Tor, будь ласка, встановіть <a href=\"https://guardianproject.info/apps/org.torproject.android/\" target=\"_blank\">додаток Orbot</a> та активуйте SOCKS5-проксі (або VPN <a href=\"https://apps.apple.com/us/app/orbot/id1609461599?platform=iphone\" target=\"_blank\">на iOS</a>).", + "simplex-private-card-5-point-1": "SimpleX використовує наповнення вмісту для кожного шару шифрування для ускладнення атак за розміром повідомлень.", + "simplex-private-card-5-point-2": "Це забезпечує, що повідомлення різних розмірів виглядають однаково для серверів та спостерігачів мережі.", + "simplex-private-card-6-point-1": "Багато комунікаційних платформ вразливі до MITM-атак серверів чи постачальників мережі.", + "simplex-private-card-6-point-2": "Щоб запобігти цьому, програми SimpleX передають одноразові ключі позаканально, коли ви ділитесь адресою як посиланням або QR-кодом.", + "simplex-private-card-7-point-2": "Якщо будь-яке повідомлення додається, вилучається чи змінюється, отримувач буде проінформований.", + "simplex-private-card-8-point-1": "Сервери SimpleX виступають як вузли низької затримки для змішування — вхідні та вихідні повідомлення мають різний порядок.", + "simplex-private-card-9-point-1": "Кожна черга повідомлень передає повідомлення в одному напрямку, з різними адресами для відправки та отримання.", + "simplex-private-card-9-point-2": "Це зменшує вектори атак порівняно із традиційними брокерами повідомлень та доступними метаданими.", + "simplex-private-card-10-point-1": "SimpleX використовує тимчасові анонімні парні адреси та облікові дані для кожного користувача, контакту чи учасника групи.", + "privacy-matters-1-title": "Реклама та дискримінація ціни", + "privacy-matters-1-overlay-1-title": "Конфіденційність зекономить вам гроші", + "privacy-matters-1-overlay-1-linkText": "Конфіденційність зекономить вам гроші", "privacy-matters-2-title": "Маніпулювання виборами", - "privacy-matters-2-overlay-1-title": "Конфіденційність дає вам силу", - "privacy-matters-3-title": "Переслідування через невинну асоціацію", + "privacy-matters-2-overlay-1-title": "Конфіденційність дає вам владу", + "privacy-matters-3-title": "Переслідування за невинним зв'язком", "privacy-matters-3-overlay-1-title": "Конфіденційність захищає вашу свободу", "privacy-matters-3-overlay-1-linkText": "Конфіденційність захищає вашу свободу", "simplex-unique-1-title": "Ви маєте повну конфіденційність", - "simplex-unique-1-overlay-1-title": "Повна конфіденційність вашої особи, профілю, контактів і метаданих", - "simplex-unique-2-title": "Ви захищені<br>від спаму та зловживань", + "simplex-unique-1-overlay-1-title": "Повна конфіденційність вашої ідентичності, профілю, контактів та метаданих", + "simplex-unique-2-title": "Вас захищено<br>від спаму та зловживань", "simplex-unique-2-overlay-1-title": "Найкращий захист від спаму та зловживань", "simplex-unique-3-title": "Ви контролюєте свої дані", - "simplex-unique-3-overlay-1-title": "Право власності, контроль та безпека ваших даних", - "simplex-unique-4-title": "Ви володієте мережею SimpleX", + "simplex-unique-3-overlay-1-title": "Власність, контроль та безпека ваших даних", + "simplex-unique-4-title": "Ви власник мережі SimpleX", "simplex-unique-4-overlay-1-title": "Повністю децентралізована — користувачі володіють мережею SimpleX", - "hero-overlay-card-1-p-1": "Багато користувачів запитували: <em>якщо SimpleX не має ідентифікаторів користувачів, як він може знати, куди доставляти повідомлення?</em>", - "hero-overlay-card-1-p-2": "Для доставки повідомлень замість ідентифікаторів користувачів, які використовуються всіма іншими платформами, SimpleX використовує тимчасові анонімні парні ідентифікатори черг повідомлень, окремі для кожного з ваших з'єднань — немає ніяких довгострокових ідентифікаторів.", - "hero-overlay-card-1-p-3": "Ви визначаєте, який сервер(и) використовувати для отримання повідомлень, ваші контакти — сервери, які ви використовуєте для надсилання їм повідомлень. У кожній розмові, швидше за все, будуть використовуватися два різних сервери.", - "hero-overlay-card-1-p-4": "Такий дизайн запобігає витоку будь-яких метаданих користувачів на рівні програми. Щоб ще більше підвищити конфіденційність і захистити свою IP-адресу, ви можете підключитися до серверів обміну повідомленнями через Tor.", - "hero-overlay-card-1-p-6": "Читайте більше в <a href='https://github.com/simplex-chat/simplexmq/blob/stable/protocol/overview-tjr.md' target='_blank'>Пропонуємо ознайомитися з технічним документом SimpleX</a>.", - "hero-overlay-card-2-p-2": "Потім вони могли співвіднести цю інформацію з існуючими публічними соціальними мережами і встановити деякі реальні особи.", - "hero-overlay-card-2-p-3": "Навіть у найбільш приватних додатках, які використовують сервіси Tor v3, якщо ви розмовляєте з двома різними контактами через один і той самий профіль, вони можуть довести, що пов'язані з однією і тією ж людиною.", - "hero-overlay-card-2-p-4": "SimpleX захищає від цих атак, не використовуючи жодних ідентифікаторів користувачів. А якщо ви використовуєте режим \"Інкогніто\", то для кожного контакту ви будете мати окреме ім'я для відображення, що дозволить уникнути обміну даними між ними.", - "simplex-network-overlay-card-1-p-1": "<a href='https://en.wikipedia.org/wiki/Peer-to-peer'>Протоколи та програми обміну повідомленнями P2P</a> мають різні проблеми, які роблять їх менш надійними, ніж SimpleX, складнішими для аналізу та вразливими до кількох типів атак.", - "simplex-network-overlay-card-1-li-1": "Мережі P2P покладаються на певний варіант <a href='https://en.wikipedia.org/wiki/Distributed_hash_table'>DHT</a> для маршрутизації повідомлень. Дизайн DHT має балансувати між гарантією доставки та затримкою. SimpleX має кращу гарантію доставки і меншу затримку, ніж P2P, тому що повідомлення може бути передано через кілька серверів паралельно, використовуючи сервери, обрані одержувачем. У P2P-мережах повідомлення передається через <em>O(log N)</em> вузлів послідовно, використовуючи вузли, обрані алгоритмом.", - "simplex-network-overlay-card-1-li-2": "Дизайн SimpleX, на відміну від більшості мереж P2P, не має жодних глобальних ідентифікаторів користувачів, навіть тимчасових, а використовує тимчасові ідентифікатори лише парами, забезпечуючи кращу анонімність і захист метаданих.", - "privacy-matters-overlay-card-1-p-1": "Багато великих компаній використовують інформацію про те, з ким ви пов'язані, щоб оцінити ваш дохід, продати вам товари, які вам насправді не потрібні, і визначити ціни.", - "privacy-matters-overlay-card-3-p-3": "Звичайних людей заарештовують за те, чим вони діляться в Інтернеті, навіть через свої 'анонімні' облікові записи, <a href='https://www.dailymail.co. uk/news/article-11282263/Moment-police-swoop-house-devout-catholic-mother-malicious-online-posts.html' target='_blank'>навіть у демократичних країнах</a>.", - "simplex-unique-overlay-card-1-p-2": "Для доставки повідомлень SimpleX використовує <a href='https://csrc.nist.gov/glossary/term/Pairwise_Pseudonymous_Identifier'>парні анонімні адреси</a> односпрямованих черг повідомлень, окремо для отриманих і відправлених повідомлень, зазвичай через різні сервери. Використання SimpleX - це все одно, що мати <strong>різну “конфорку” електронну пошту або телефон для кожного контакту</strong>, і не мати клопоту з управлінням ними.", - "simplex-unique-overlay-card-1-p-3": "Такий дизайн захищає конфіденційність того, з ким ви спілкуєтеся, приховуючи її від серверів платформи SimpleX і від будь-яких спостерігачів. Щоб приховати свою IP-адресу від серверів, ви можете <strong>підключитися до серверів SimpleX через Tor</strong>.", - "simplex-unique-overlay-card-2-p-1": "Оскільки у вас немає ідентифікатора на платформі SimpleX, ніхто не може зв'язатися з вами, якщо ви не надасте одноразову або тимчасову адресу користувача у вигляді QR-коду або посилання.", - "simplex-unique-overlay-card-2-p-2": "Навіть якщо необов'язкова адреса користувача може бути використана для надсилання спам-повідомлень, ви можете змінити або повністю видалити її, не втрачаючи при цьому жодного з ваших зв'язків.", - "simplex-unique-overlay-card-3-p-1": "SimpleX Chat зберігає всі дані користувача лише на клієнтських пристроях за допомогою <strong>портативного формату зашифрованої бази даних</strong>, який можна експортувати та передавати на будь-який підтримуваний пристрій.", - "simplex-unique-overlay-card-3-p-2": "Наскрізні зашифровані повідомлення тимчасово зберігаються на релейних серверах SimpleX до моменту отримання, після чого вони назавжди видаляються.", - "simplex-unique-overlay-card-3-p-4": "Між відправленим і отриманим трафіком сервера немає спільних ідентифікаторів або зашифрованого тексту — якщо хтось спостерігає за ним, він не зможе легко визначити, хто з ким спілкується, навіть якщо TLS скомпрометований.", - "simplex-unique-overlay-card-4-p-1": "Ви можете <strong>використовувати SimpleX з власними серверами</strong> і при цьому спілкуватися з людьми, які використовують попередньо налаштовані сервери, надані нами.", - "simplex-unique-overlay-card-4-p-2": "Платформа SimpleX використовує <a href='https://github.com/simplex-chat/simplexmq/blob/stable/protocol/overview-tjr.md' target='_blank'>відкритий протокол</a> та надає <a href='https://github.com/simplex-chat/simplex-chat/tree/stable/packages/simplex-chat-client/typescript' target='_blank'>SDK для створення чат-ботів</a>, що дозволяє реалізовувати сервіси, з якими користувачі можуть взаємодіяти через додатки SimpleX Chat —. Ми'з нетерпінням чекаємо на те, які сервіси SimpleX ви можете створити.", - "simplex-unique-overlay-card-4-p-3": "Якщо ви розглядаєте можливість розробки для платформи SimpleX, наприклад, чат-бота для користувачів додатків SimpleX або інтеграції бібліотеки SimpleX Chat у ваші мобільні додатки, будь ласка, <a href='https://simplex.chat/contact#/?v=1&smp=smp%3A%2F%2FPQUV2eL0t7OStZOoAsPEV2QYWt4-xilbakvGUGOItUo%3D%40smp6.simplex.im%2FK1rslx-m5bpXVIdMZg9NLUZ_8JBm8xTt%23MCowBQYDK2VuAyEALDeVe-sG8mRY22LsXlPgiwTNs9dbiLrNuA7f3ZMAJ2w%3D' target='_blank'>зв'яжіться з нами</a> для отримання будь-якої консультації та підтримки.", - "simplex-unique-card-1-p-1": "SimpleX захищає конфіденційність вашого профілю, контактів і метаданих, приховуючи їх від серверів платформи SimpleX і будь-яких спостерігачів.", - "simplex-unique-card-1-p-2": "На відміну від будь-якої іншої існуючої платформи обміну повідомленнями, SimpleX не має ніяких ідентифікаторів, призначених користувачам — <strong>, навіть випадкових чисел</strong>.", - "simplex-unique-card-2-p-1": "Оскільки у вас немає ідентифікатора або фіксованої адреси на платформі SimpleX, ніхто не може зв'язатися з вами, якщо ви не надасте одноразову або тимчасову адресу користувача, наприклад, у вигляді QR-коду або посилання.", - "simplex-unique-card-3-p-1": "SimpleX зберігає всі дані користувача на клієнтських пристроях у <strong>портативному форматі зашифрованої бази даних </strong> —, його можна перенести на інший пристрій.", - "join": "Приєднуйтесь", - "we-invite-you-to-join-the-conversation": "Запрошуємо вас долучитися до розмови", + "hero-overlay-card-1-p-1": "Багато користувачів запитували: <em>якщо у SimpleX немає ідентифікаторів користувачів, як він може знати, куди відправити повідомлення?</em>", + "hero-overlay-card-1-p-2": "Для доставки повідомлень, замість ідентифікаторів користувачів, які використовують усі інші платформи, SimpleX використовує тимчасові анонімні парні ідентифікатори черг повідомлень, окремі для кожного вашого підключення — тут немає довгострокових ідентифікаторів.", + "hero-overlay-card-1-p-3": "Ви визначаєте, який(кі) сервер(и) використовувати для отримання повідомлень, ваші контакти — сервери, які ви використовуєте для відправки повідомлень їм. Кожна розмова, ймовірно, використовує два різних сервери.", + "hero-overlay-card-1-p-4": "Цей дизайн запобігає витоку метаданих будь-яких користувачів на рівні додатка. Для подальшого покращення конфіденційності та захисту вашої IP-адреси ви можете підключитися до серверів обміну повідомленнями через Tor.", + "hero-overlay-card-1-p-6": "Докладніше читайте у <a href='https://github.com/simplex-chat/simplexmq/blob/stable/protocol/overview-tjr.md' target='_blank'>білетному запису SimpleX</a>.", + "hero-overlay-card-2-p-2": "Вони можуть потім корелювати цю інформацію з існуючими громадськими соціальними мережами та визначати деякі реальні ідентифікатори.", + "hero-overlay-card-2-p-3": "Навіть з найбільш приватними додатками, які використовують служби Tor v3, якщо ви розмовляєте з двома різними контактами через той самий профіль, вони можуть довести, що вони підключені до однієї й тієї ж особи.", + "hero-overlay-card-2-p-4": "SimpleX захищає від цих атак, не маючи жодних ідентифікаторів користувачів в своєму дизайні. І, якщо ви використовуєте режим інкогніто, у вас буде різне відображення для кожного контакту, уникнення будь-яких спільних даних між ними.", + "simplex-network-overlay-card-1-p-1": "<a href='https://en.wikipedia.org/wiki/Peer-to-peer'>Протоколи та додатки для P2P-зв'язку</a> мають різні проблеми, які роблять їх менш надійними порівняно із SimpleX, складнішими для аналізу та вразливими до кількох типів атак.", + "simplex-network-overlay-card-1-li-1": "P2P-мережі покладаються на якусь варіацію <a href='https://en.wikipedia.org/wiki/Distributed_hash_table'>розподіленої хеш-таблиці (DHT)</a> для маршрутизації повідомлень. Дизайни DHT повинні балансувати гарантію доставки та затримку. У SimpleX є як краща гарантія доставки, так і менша затримка порівняно із P2P, оскільки повідомлення може передаватися паралельно кількома серверами, використовуючи сервери, обрані отримувачем. У P2P-мережах повідомлення проходить через вузли <em>O(log N)</em> послідовно, використовуючи вузли, обрані алгоритмом.", + "simplex-network-overlay-card-1-li-2": "У дизайні SimpleX, на відміну від більшості P2P-мереж, немає жодних глобальних ідентифікаторів користувачів будь-якого виду, навіть тимчасових, та використовуються лише тимчасові парні ідентифікатори, що забезпечує кращу анонімність та захист метаданих.", + "privacy-matters-overlay-card-1-p-1": "Багато великих компаній використовують інформацію про те, з ким ви з'єднані, щоб оцінити ваш дохід, продавати вам продукти, які вам дійсно не потрібні, і визначати ціни.", + "privacy-matters-overlay-card-3-p-3": "Звичайних людей арештовують за те, що вони публікують онлайн, навіть через свої 'анонімні' облікові записи, <a href='https://www.dailymail.co.uk/news/article-11282263/Moment-police-swoop-house-devout-catholic-mother-malicious-online-posts.html' target='_blank'>навіть у демократичних країнах</a>.", + "simplex-unique-overlay-card-1-p-2": "Для доставки повідомлень SimpleX використовує <a href='https://csrc.nist.gov/glossary/term/Pairwise_Pseudonymous_Identifier'>парні анонімні адреси</a> однобічних черг повідомлень, окремо для отриманих та відправлених повідомлень, зазвичай через різні сервери. Використання SimpleX схоже на наявність <strong>різної “витратної” електронної пошти або телефону для кожного контакту</strong>, і немає неприємностей у їх управлінні.", + "simplex-unique-overlay-card-1-p-3": "Цей дизайн захищає конфіденційність осіб, з якими ви спілкуєтеся, приховуючи це від серверів платформи SimpleX та будь-яких спостерігачів. Щоб сховати свою IP-адресу від серверів, ви можете <strong>підключитися до серверів SimpleX через Tor</strong>.", + "simplex-unique-overlay-card-2-p-1": "Оскільки у вас немає ідентифікатора на платформі SimpleX, ніхто не може з вами зв'язатися, якщо ви не поділитеся одноразовою або тимчасовою адресою користувача, у вигляді QR-коду або посилання.", + "simplex-unique-overlay-card-2-p-2": "Навіть з необов'язковою адресою користувача, яка може бути використана для відправки спамових запитань на зв'язок, ви можете змінити або повністю видалити її, не втрачаючи жодного з ваших з'єднань.", + "simplex-unique-overlay-card-3-p-1": "SimpleX Chat зберігає всі дані користувачів лише на пристроях клієнтів за допомогою <strong>переносного зашифрованого формату бази даних</strong>, який можна експортувати і передавати на будь-який підтримуваний пристрій.", + "simplex-unique-overlay-card-3-p-2": "Зашифровані повідомлення від кінця до кінця тимчасово зберігаються на ретрансляційних серверах SimpleX до їх отримання, після чого вони назавжди видаляються.", + "simplex-unique-overlay-card-3-p-4": "Між надісланим і отриманим серверним трафіком немає спільних ідентифікаторів чи шифрованого тексту — якщо хтось його спостерігає, він не може легко визначити, хто спілкується з ким, навіть якщо TLS скомпрометовано.", + "simplex-unique-overlay-card-4-p-1": "Ви можете <strong>використовувати SimpleX з власними серверами</strong> і все одно спілкуватися з людьми, які використовують надані нам сервери заздалегідь налаштовані.", + "simplex-unique-overlay-card-4-p-2": "Платформа SimpleX використовує <a href='https://github.com/simplex-chat/simplexmq/blob/stable/protocol/overview-tjr.md' target='_blank'>відкритий протокол</a> та надає <a href='https://github.com/simplex-chat/simplex-chat/tree/stable/packages/simplex-chat-client/typescript' target='_blank'>SDK для створення чат-ботів</a>, що дозволяє впроваджувати сервіси, з якими користувачі можуть взаємодіяти через додатки SimpleX Chat — ми дійсно чекаємо, які сервіси SimpleX ви зможете побудувати.", + "simplex-unique-overlay-card-4-p-3": "Якщо ви розглядаєте можливість розробки для платформи SimpleX, наприклад, чат-бота для користувачів додатку SimpleX або інтеграції бібліотеки SimpleX Chat у свої мобільні додатки, будь ласка, <a href='https://simplex.chat/contact#/?v=1&smp=smp%3A%2F%2FPQUV2eL0t7OStZOoAsPEV2QYWt4-xilbakvGUGOItUo%3D%40smp6.simplex.im%2FK1rslx-m5bpXVIdMZg9NLUZ_8JBm8xTt%23MCowBQYDK2VuAyEALDeVe-sG8mRY22LsXlPgiwTNs9dbiLrNuA7f3ZMAJ2w%3D' target='_blank'>зв'яжіться з нами</a> для отримання порад та підтримки.", + "simplex-unique-card-1-p-1": "SimpleX захищає конфіденційність вашого профілю, контактів та метаданих, приховуючи їх від серверів платформи SimpleX та будь-яких спостерігачів.", + "simplex-unique-card-1-p-2": "На відміну від будь-якої іншої існуючої платформи обміну повідомленнями, SimpleX не має ідентифікаторів, призначених користувачам — <strong>навіть випадкових чисел</strong>.", + "simplex-unique-card-2-p-1": "Оскільки у вас немає ідентифікатора або фіксованої адреси на платформі SimpleX, ніхто не може з вами зв'язатися, якщо ви не поділитесь одноразовою або тимчасовою адресою користувача, як QR-код або посиланням.", + "simplex-unique-card-3-p-1": "SimpleX зберігає всі дані користувачів на пристроях клієнтів у <strong>переносному зашифрованому форматі бази даних</strong> — його можна передавати на інший пристрій.", + "join": "Приєднатися", + "we-invite-you-to-join-the-conversation": "Ми запрошуємо вас приєднатися до розмови", "join-the-REDDIT-community": "Приєднуйтесь до спільноти REDDIT", "join-us-on-GitHub": "Приєднуйтесь до нас на GitHub", "donate-here-to-help-us": "Пожертвуйте тут, щоб допомогти нам", - "sign-up-to-receive-our-updates": "Підпишіться на наші оновлення", - "enter-your-email-address": "Введіть адресу вашої електронної пошти", - "get-simplex": "Отримати SimpleX <a href=\"/downloads\">desktop app</a>", - "why-simplex-is": "Чому SimpleX це", - "unique": "унікальний", - "learn-more": "Дізнайтеся більше", - "more-info": "Більше інформації", + "sign-up-to-receive-our-updates": "Підпишіться, щоб отримувати наші оновлення", + "enter-your-email-address": "Введіть свою електронну адресу", + "get-simplex": "Отримати SimpleX <a href=\"/downloads\">додаток для настільних комп'ютерів</a>", + "why-simplex-is": "Чому SimpleX є", + "unique": "унікальним", + "learn-more": "Дізнатися більше", + "more-info": "Додаткова інформація", "hide-info": "Приховати інформацію", - "contact-hero-header": "Ви отримали адресу для підключення до чату SimpleX", - "invitation-hero-header": "Ви отримали одноразове посилання для підключення до чату SimpleX", - "contact-hero-subheader": "Відскануйте QR-код за допомогою програми SimpleX Chat на телефоні або планшеті.", + "contact-hero-header": "Ви отримали адресу для підключення в SimpleX Chat", + "invitation-hero-header": "Ви отримали 1-разове посилання для підключення в SimpleX Chat", + "contact-hero-subheader": "Скануйте QR-код за допомогою додатка SimpleX Chat на своєму телефоні чи планшеті.", "contact-hero-p-2": "Ще не завантажили SimpleX Chat?", - "contact-hero-p-3": "Щоб завантажити додаток, скористайтеся посиланнями нижче.", - "connect-in-app": "Підключіться в додатку", - "open-simplex-app": "Відкрийте програму Simplex", - "tap-the-connect-button-in-the-app": "Натисніть кнопку <span class='text-active-blue'>‘підключитися‘</span> у додатку", - "scan-the-qr-code-with-the-simplex-chat-app": "Відскануйте QR-код за допомогою програми SimpleX Chat", - "scan-the-qr-code-with-the-simplex-chat-app-description": "Відкриті ключі та адреса черги повідомлень за цим посиланням НЕ передаються мережею при перегляді цієї сторінки —<br> вони містяться в хеш-фрагменті URL-адреси посилання.", - "installing-simplex-chat-to-terminal": "Встановлення чату SimpleX на термінал", - "use-this-command": "Використовуй цю команду:", - "see-simplex-chat": "Дивіться Чат SimpleX", - "the-instructions--source-code": "інструкції, як завантажити або скомпілювати його з вихідного коду.", + "contact-hero-p-3": "Скористайтеся посиланнями нижче, щоб завантажити додаток.", + "connect-in-app": "Підключитися в додатку", + "open-simplex-app": "Відкрити додаток SimpleX", + "tap-the-connect-button-in-the-app": "Торкніться кнопки <span class='text-active-blue'>‘підключити’</span> в додатку", + "scan-the-qr-code-with-the-simplex-chat-app": "Скануйте QR-код за допомогою додатка SimpleX Chat", + "scan-the-qr-code-with-the-simplex-chat-app-description": "Публічні ключі та адреса черги повідомлень в цьому посиланні НЕ відправляються по мережі під час перегляду цієї сторінки —<br> вони містяться в хеш-фрагменті URL-посилання.", + "installing-simplex-chat-to-terminal": "Встановлення SimpleX Chat для терміналу", + "use-this-command": "Використовуйте цю команду:", + "see-simplex-chat": "Дивіться SimpleX Chat", + "the-instructions--source-code": "інструкції з того, як його завантажити чи скомпілювати з вихідного коду.", "if-you-already-installed-simplex-chat-for-the-terminal": "Якщо ви вже встановили SimpleX Chat для терміналу", "if-you-already-installed": "Якщо ви вже встановили", "simplex-chat-for-the-terminal": "SimpleX Chat для терміналу", - "copy-the-command-below-text": "скопіюйте команду нижче і використовуйте її в чаті:", + "copy-the-command-below-text": "скопіюйте команду нижче та використовуйте її в чаті:", "privacy-matters-section-header": "Чому конфіденційність <span class='gradient-text'>має значення</span>", - "privacy-matters-section-subheader": "Збереження конфіденційності ваших метаданих — <span class='text-active-blue'>від кого ви спілкуєтеся</span> — захищає вас:", - "privacy-matters-section-label": "Переконайтеся, що ваш месенджер не може отримати доступ до ваших даних!", - "simplex-private-section-header": "Що робить SimpleX <span class='gradient-text'>приватним</span>", - "tap-to-close": "Натисніть, щоб закрити", - "simplex-network-section-header": "SimpleX <span class='gradient-text'>Мережа</span>", - "simplex-network-section-desc": "Simplex Chat забезпечує найкращу конфіденційність, поєднуючи переваги P2P та об'єднаних мереж.", - "simplex-network-1-desc": "Всі повідомлення надсилаються через сервери, що забезпечує кращу конфіденційність метаданих і надійну асинхронну доставку повідомлень, уникаючи при цьому багатьох", - "simplex-network-1-header": "На відміну від P2P-мереж", - "simplex-network-1-overlay-linktext": "проблеми P2P-мереж", - "simplex-network-2-header": "На відміну від об'єднаних мереж", - "simplex-network-2-desc": "Сервери ретрансляції SimpleX НЕ зберігають профілі користувачів, контакти та доставлені повідомлення, НЕ з'єднуються один з одним і НЕ мають каталогу серверів.", + "privacy-matters-section-subheader": "Збереження конфіденційності ваших метаданих — <span class='text-active-blue'>з ким ви спілкуєтеся</span> — захищає вас від:", + "privacy-matters-section-label": "Переконайтеся, що ваш месенджер не має доступу до ваших даних!", + "simplex-private-section-header": "Що робить SimpleX <span class='gradient-text'>конфіденційним</span>", + "tap-to-close": "Торкніться, щоб закрити", + "simplex-network-section-header": "SimpleX <span class='gradient-text'>Network</span>", + "simplex-network-section-desc": "Simplex Chat надає найкращу конфіденційність, поєднуючи переваги P2P та федеративних мереж.", + "simplex-network-1-desc": "Всі повідомлення відправляються через сервери, що забезпечує кращу конфіденційність метаданих та надійну асинхронну доставку повідомлень, уникаючи багатьох", + "simplex-network-1-header": "На відміну від мереж P2P", + "simplex-network-1-overlay-linktext": "проблем P2P-мереж", + "simplex-network-2-header": "На відміну від федеративних мереж", + "simplex-network-2-desc": "Сервери SimpleX Chat НЕ зберігають профілі користувачів, контакти та доставлені повідомлення, НЕ підключаються один до одного, і НЕ існує каталог серверів.", "simplex-network-3-header": "Мережа SimpleX", - "simplex-network-3-desc": "Сервери надають <span class='text-active-blue'>односпрямовані черги</span> для підключення користувачів, але вони не мають видимості графу мережевих з'єднань —, його бачать лише користувачі.", + "simplex-network-3-desc": "сервери надають <span class='text-active-blue'>однобічні черги</span> для з'єднання користувачів, але вони не мають видимості графа підключень в мережі — лише користувачі.", "comparison-section-header": "Порівняння з іншими протоколами", - "protocol-1-text": "Сигнал, великі платформи", - "protocol-2-text": "XMPP, Матрикс", + "protocol-1-text": "Signal, великі платформи", + "protocol-2-text": "XMPP, Matrix", "protocol-3-text": "Протоколи P2P", - "comparison-point-1-text": "Вимагає глобальної ідентичності", + "comparison-point-1-text": "Потребує глобального ідентифікатора", "comparison-point-2-text": "Можливість MITM", "comparison-point-3-text": "Залежність від DNS", - "comparison-point-4-text": "Окрема або централізована мережа", - "comparison-point-5-text": "Атака на центральний компонент або інша мережева атака", + "comparison-point-4-text": "Одна чи централізована мережа", + "comparison-point-5-text": "Центральний компонент чи інша атака на всю мережу", "yes": "Так", "no": "Ні", - "no-private": "Ні - приватний", + "no-private": "Ні - конфіденційно", "no-secure": "Ні - безпечно", - "no-resilient": "Ні - стійкий", + "no-resilient": "Ні - стійко", "no-decentralized": "Ні - децентралізовано", - "comparison-section-list-point-4": "Якщо сервери оператора скомпрометовані", - "comparison-section-list-point-5": "Не захищає метадані користувачів", - "comparison-section-list-point-6": "Хоча P2P розподілені, вони не об'єднані - вони працюють як єдина мережа", + "comparison-section-list-point-4": "Якщо сервери оператора порушені. Перевірте безпековий код в Signal та деяких інших додатках для зменшення ризику", + "comparison-section-list-point-5": "Не захищає конфіденційність метаданих користувачів", + "comparison-section-list-point-6": "Хоча P2P є розподіленими, вони не є федеративними - вони працюють як єдина мережа", "guide-dropdown-1": "Швидкий старт", - "guide-dropdown-2": "Надсилання повідомлень", + "guide-dropdown-2": "Відправлення повідомлень", "guide-dropdown-3": "Таємні групи", "glossary": "Глосарій", "docs-dropdown-8": "Служба каталогів SimpleX", - "f-droid-page-simplex-chat-repo-section-text": "Щоб додати його в клієнт F-Droid <span class='hide-on-mobile'>відскануйте QR-код або</span> використовуйте цю URL-адресу:", + "f-droid-page-simplex-chat-repo-section-text": "Щоб додати його до свого клієнта F-Droid, <span class='hide-on-mobile'>скануйте QR-код або</span> використовуйте цей URL:", "simplex-chat-via-f-droid": "SimpleX Chat через F-Droid", - "signing-key-fingerprint": "Відбиток ключа підпису (SHA-256)", - "stable-versions-built-by-f-droid-org": "Стабільні версії, зібрані на F-Droid.org", - "simplex-chat-repo": "Репо SimpleX Chat", - "f-droid-org-repo": "Репо F-Droid.org", - "releases-to-this-repo-are-done-1-2-days-later": "Релізи в це репо відбуваються на 1-2 дні пізніше", - "stable-and-beta-versions-built-by-developers": "Стабільні та бета-версії, створені розробниками", - "f-droid-page-f-droid-org-repo-section-text": "Репозиторії SimpleX Chat та F-Droid.org підписують збірки з різними ключами. Щоб перемикнутися, будь ласка <a href='/docs/guide/chat-profiles.html#move-your-chat-profiles-to-another-device'>експорт</a> базу даних чату та перевстановіть додаток." + "signing-key-fingerprint": "Відбиток підпису ключа (SHA-256)", + "stable-versions-built-by-f-droid-org": "Стабільні версії, побудовані F-Droid.org", + "simplex-chat-repo": "Репозитарій SimpleX Chat", + "f-droid-org-repo": "Репозитарій F-Droid.org", + "releases-to-this-repo-are-done-1-2-days-later": "Релізи в цей репозитарій робляться за 1-2 дні пізніше", + "stable-and-beta-versions-built-by-developers": "Стабільні та бета-версії, побудовані розробниками", + "f-droid-page-f-droid-org-repo-section-text": "SimpleX Chat та репозитарії F-Droid.org підписують збірки різними ключами. Щоб переключитися, будь ласка, <a href='/docs/guide/chat-profiles.html#move-your-chat-profiles-to-another-device'>експортуйте</a> базу даних чату та перевстановіть додаток.", + "hero-overlay-3-title": "Оцінка безпеки", + "hero-overlay-card-3-p-2": "Trail of Bits переглянувало криптографію та компоненти мережі платформи SimpleX у листопаді 2022 року.", + "hero-overlay-card-3-p-3": "Читайте більше в <a href=\"/blog/20221108-simplex-chat-v4.2-security-audit-new-website.html\">оголошенні</a>.", + "jobs": "Приєднатися до команди", + "hero-overlay-3-textlink": "Оцінка безпеки", + "hero-overlay-card-3-p-1": "<a href=\"https://www.trailofbits.com/about/\">Trail of Bits</a> є провідною консалтинговою фірмою з безпеки та технологій, клієнтами якої є великі технологічні компанії, урядові агенції та великі проекти у сфері блокчейну.", + "comparison-section-list-point-4a": "Ретранслятори SimpleX не можуть порушити e2e-шифрування. Перевірте безпековий код для зменшення ризику атаки на зовнішньобандовий канал", + "docs-dropdown-9": "Завантаження" } \ No newline at end of file diff --git a/website/langs/zh_Hans.json b/website/langs/zh_Hans.json index 8fb012963a..e787bced83 100644 --- a/website/langs/zh_Hans.json +++ b/website/langs/zh_Hans.json @@ -34,7 +34,7 @@ "simplex-network-1-header": "与 P2P 网络不同", "simplex-network-1-overlay-linktext": "P2P网络存在的问题", "simplex-network-2-header": "不同于联邦网络", - "comparison-point-1-text": "需要全球身份", + "comparison-point-1-text": "需要全局身份", "no-secure": "不可能 - 安全", "simplex-privacy": "SimpleX 的隐私性", "home": "主页", @@ -175,21 +175,21 @@ "tap-to-close": "点击关闭", "simplex-network-section-header": "SimpleX <span class='gradient-text'>网络</span>", "simplex-network-section-desc": "Simplex Chat 通过结合 P2P 和联邦网络的优势使其保密性无与伦比。", - "no-private": "不需要 - 私密", + "no-private": "否 - 私密", "simplex-network-1-desc": "所有消息都通过服务器发送,既能更好地保护元数据隐私和可靠地传递异步消息,同时也能避免许多", - "simplex-network-3-header": "SimpleX网络", + "simplex-network-3-header": "SimpleX 网络", "protocol-1-text": "Signal、其他大平台", - "comparison-point-4-text": "单一或集中式网络", + "comparison-point-4-text": "单一或中心化网络", "simplex-network-3-desc": "服务器提供<span class='text-active-blue'>单向队列</span>来连接用户,但是他们看不到网络连接图图谱— 只有用户可以。", "comparison-section-header": "与其他协议的比较", "protocol-3-text": "P2P协议", - "no": "不需要", + "no": "否", "comparison-point-3-text": "对 DNS 的依赖", "no-federated": "不依赖 - 联邦式网络", "protocol-2-text": "XMPP、Matrix", "comparison-point-2-text": "中间人攻击的可能性", "comparison-point-5-text": "中央组件或其他全网攻击", - "yes": "需要", + "yes": "是", "comparison-section-list-point-5": "不保护用户的元数据", "no-resilient": "不依赖 - 有韧性", "no-decentralized": "不依赖 - 去中心化的", @@ -199,7 +199,7 @@ "comparison-section-list-point-2": "基于 DNS 的地址", "comparison-section-list-point-6": "P2P 是分布式的,而非联邦式的 - 它们作为单个网络运行", "see-here": "参见此处", - "comparison-section-list-point-7": "P2P 网络要么拥有中央管理机制,要么整个网络都可能受到损害", + "comparison-section-list-point-7": "P2P 网络要么拥有中央权威,要么整个网络可能被攻陷", "simplex-private-card-5-point-1": "SimpleX 为每个加密层进行内容填充来对抗长度扩展攻击。", "simplex-unique-overlay-card-4-p-2": "SimpleX 平台使用<a href='https://github.com/simplex-chat/simplexmq/blob/stable/protocol/overview-tjr.md' target='_blank'>开放协议</a>并提供<a href='https://github.com/simplex-chat/simplex-chat/tree/stable/packages/simplex-chat-client/typescript' target='_blank'>用于创建聊天机器人的 SDK</a>, 允许用户实现通过 SimpleX Chat 应用程序与之交互的服务—— 我们真的很期待看到您可以依托SimpleX构建哪些服务。", "simplex-unique-overlay-card-2-p-2": "即使使用可选的用户地址,当它被用于发送垃圾邮件联系请求,您可以更改或完全删除它而不会丢失任何连接。", diff --git a/website/src/_includes/blog_previews/20240124.html b/website/src/_includes/blog_previews/20240124.html new file mode 100644 index 0000000000..799e75426c --- /dev/null +++ b/website/src/_includes/blog_previews/20240124.html @@ -0,0 +1,20 @@ +<p><strong>SimpleX Chat infrastructure on Linode:</strong></p> + +<ul class="mb-[12px]"> + <li>free infrastructure.</li> + <li>SimpleX servers in Linode Marketplace.</li> + <li>high capacity messaging servers.</li> +</ul> + +<p><strong>v5.5 is released:</strong></p> + +<ul class="mb-[12px]"> + <li>private notes.</li> + <li>group history</li> + <li>simpler UX to connect to other people</li> + <li>message delivery, battery usage and other improvements</li> +</ul> + +<p>Also, the app interface is now available in Hungarian and Turkish - thanks to our users.</p> + +<p>SimpleX Chat Android and desktop apps are now available in 20 languages!</p> \ No newline at end of file